]> git.vomp.tv Git - vompclient-marten.git/commitdiff
Portability
authorChris Tallon <chris@vomp.tv>
Sun, 26 Mar 2006 16:02:33 +0000 (16:02 +0000)
committerChris Tallon <chris@vomp.tv>
Sun, 26 Mar 2006 16:02:33 +0000 (16:02 +0000)
19 files changed:
Makefile
box.cc
box.h
colour.h
defines.h
main.cc
osdmvp.cc
osdmvp.h
player.cc
surface.cc
surface.h
surfacemvp.cc [new file with mode: 0644]
surfacemvp.h [new file with mode: 0644]
surfacewin.cc [new file with mode: 0644]
surfacewin.h [new file with mode: 0644]
vepg.cc
view.cc
viewman.cc
viewman.h

index 3b5bc3bbe466dd1cc7eb034a5911feeb3d024d03..c4e14149b92a0b6e68671d2999a7301098256398 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,8 @@ OBJECTS1 = main.o command.o log.o tcp.o dsock.o thread.o timers.o i18n.o
 OBJECTS2 = remote.o led.o mtd.o video.o audio.o osd.o surface.o                        \
            audiomvp.o audiowin.o                                                       \
            videomvp.o videowin.o                                                       \
-           osdmvp.o osdwin.o
+           osdmvp.o osdwin.o                                                           \
+           surfacemvp.o surfacewin.o
 
 OBJECTS = $(OBJECTS1) $(OBJECTS2)
 
diff --git a/box.cc b/box.cc
index 9c8120bd34e39545b6da38e1e51af3194947a5e3..f4e590a776ead1353a7b67c079c30eb828aba7d1 100644 (file)
--- a/box.cc
+++ b/box.cc
@@ -187,29 +187,29 @@ void Box::drawPara(char* text, int x, int y, Colour& colour)
 
 // Level 0 drawing functions
 
-void Box::rectangle(int x1, int y1, int w, int h, Colour& colour)
+void Box::rectangle(int x1, int y1, int w, int h, Colour colour)
 {
-  surface->fillblt(offsetX + x1, offsetY + y1, w, h, surface->rgba(colour.red, colour.green, colour.blue, colour.alpha));
+  surface->fillblt(offsetX + x1, offsetY + y1, w, h, colour.rgba());
 }
 
 void Box::rectangle(Region& region, Colour& colour)
 {
-  surface->fillblt(offsetX + region.x, offsetY + region.y, region.w, region.h, surface->rgba(colour.red, colour.green, colour.blue, colour.alpha));
+  surface->fillblt(offsetX + region.x, offsetY + region.y, region.w, region.h, colour.rgba());
 }
 
 void Box::drawText(char* text, int x, int y, Colour& colour)
 {
-  surface->drawText(text, offsetX + x, offsetY + y, colour.red, colour.green, colour.blue);
+  surface->drawText(text, offsetX + x, offsetY + y, colour.rgba());
 }
 
 void Box::drawTextRJ(char* text, int x, int y, Colour& colour)
 {
-  surface->drawTextRJ(text, offsetX + x, offsetY + y, colour.red, colour.green, colour.blue);
+  surface->drawTextRJ(text, offsetX + x, offsetY + y, colour.rgba());
 }
 
 void Box::drawTextCentre(char* text, int x, int y, Colour& colour)
 {
-  surface->drawTextCentre(text, offsetX + x, offsetY + y, colour.red, colour.green, colour.blue);
+  surface->drawTextCentre(text, offsetX + x, offsetY + y, colour.rgba());
 }
 
 void Box::drawPixel(UINT x, UINT y, Colour& colour)
diff --git a/box.h b/box.h
index 06de5004c53df345ed6c9c0ed8b8222abefd81d9..839e352d7b1ffd888ed90d9dde9e51108928d0eb 100644 (file)
--- a/box.h
+++ b/box.h
 
 #include "log.h"
 #include "colour.h"
-#include "surface.h"
 #include "region.h"
 
+#ifdef WIN32
+#include "surfacewin.h"
+#else
+#include "surfacemvp.h"
+#endif
+
 // Abstract ???????
 class Box
 {
@@ -48,7 +53,7 @@ class Box
     void drawPara(char* text, int x, int y, Colour& colour);
 
     // Drawing functions level 0
-    void rectangle(int x1, int y1, int w, int h, Colour& colour);
+    void rectangle(int x, int y, int w, int h, Colour colour); // FIXME make this ref again
     void rectangle(Region& region, Colour& colour);
 
     void drawText(char* text, int x, int y, Colour& colour);
index 9067e2ae38dd2d7c6affa6ee85c64a2f75a337f5..34b860f3d2254cc5b5ba378208286994c4250e62 100644 (file)
--- a/colour.h
+++ b/colour.h
@@ -39,6 +39,11 @@ class Colour
     void set(int Tred, int Tgreen, int Tblue, int Talpha)
       { red = Tred; green = Tgreen; blue = Tblue; alpha = Talpha; }
 
+    unsigned long rgba()
+    {
+      return (alpha << 24) | (red << 16) | (green << 8) | blue;
+    }
+
     int red;
     int green;
     int blue;
index 8ab58db613acbd5a9ab0cd92687699b444788e51..8c3b1eee22d378c98d545d676400ed7fa47e182f 100644 (file)
--- a/defines.h
+++ b/defines.h
@@ -35,17 +35,25 @@ ULLONG ntohll(ULLONG a);
 void MILLISLEEP(ULONG a);
 
 #ifdef WIN32
-#define SNPRINTF _snprintf
-#define VSNPRINTF _vsnprintf
-#define STRCASECMP stricmp
-#define STRCASESTR StrStrI
-#define STRTOULL _strtoui64
+
+  #define Surface_TYPE SurfaceWin
+
+  #define SNPRINTF _snprintf
+  #define VSNPRINTF _vsnprintf
+  #define STRCASECMP stricmp
+  #define STRCASESTR StrStrI
+  #define STRTOULL _strtoui64
+
 #else
-#define SNPRINTF snprintf
-#define VSNPRINTF vsnprintf
-#define STRCASECMP strcasecmp
-#define STRCASESTR strcasestr
-#define STRTOULL strtoull
+
+  #define Surface_TYPE SurfaceMVP
+
+  #define SNPRINTF snprintf
+  #define VSNPRINTF vsnprintf
+  #define STRCASECMP strcasecmp
+  #define STRCASESTR strcasestr
+  #define STRTOULL strtoull
+
 #endif
 
 #endif
diff --git a/main.cc b/main.cc
index 5ff34bc1666190dce111f66800db93d27d1d549b..70259b33e644ae98429cb6f8e8a6259be3f38650 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -467,7 +467,6 @@ void MILLISLEEP(ULONG a)
   struct timespec delayTime;
   delayTime.tv_sec = a / 1000;
   delayTime.tv_nsec = (a % 1000) * 1000000;
-  printf("%lu %lu\n", delayTime.tv_sec, delayTime.tv_nsec);
   nanosleep(&delayTime, NULL);
 #else
   Sleep(a);
index b4fda692d581c02545b3f68ed64259083829c9a6..a86f9a01f13b68ef91c3ccb8298bfb0274cd3292 100644 (file)
--- a/osdmvp.cc
+++ b/osdmvp.cc
@@ -49,11 +49,11 @@ int OsdMVP::init(char* device)
 
   initted = 1; // must set this here or create surface won't work
 
-  Surface::initConversionTables();
+  SurfaceMVP::initConversionTables();
 
   Video* video = Video::getInstance();
 
-  screen = new Surface(Surface::SCREEN);
+  screen = new SurfaceMVP(Surface::SCREEN);
   screen->create(video->getScreenWidth(), video->getScreenHeight());
   screen->display();
 
index dbea737aa1cd9b7d20ea431f3867c5eb34c5ec02..5b6dfc407a6846284682c484ed95405cfd691f10 100644 (file)
--- a/osdmvp.h
+++ b/osdmvp.h
@@ -28,7 +28,7 @@
 #include "osd.h"
 #include "defines.h"
 #include "log.h"
-#include "surface.h"
+#include "surfacemvp.h"
 #include "video.h"
 
 class OsdMVP : public Osd
index c0893af9360207eea002c98b2dc1edeab71772f7..faf14362c692701d6cf8bb4975f975acb0dc59e7 100644 (file)
--- a/player.cc
+++ b/player.cc
@@ -112,7 +112,7 @@ void Player::resyncAudio()
   // Temp hopefully
   if (!initted) return;
   audio->pause();
-  usleep(500000);
+  MILLISLEEP(500);
   audio->unPause();
 }
 
@@ -121,7 +121,7 @@ void Player::resyncVideo()
   // Temp hopefully
   if (!initted) return;
   video->pause();
-  usleep(500000);
+  MILLISLEEP(500);
   video->unPause();
 }
 
@@ -179,25 +179,15 @@ int Player::play()
 
 /*
   threadStart();
-//  sleep(1);
-
-//  struct timespec delay;
-//  delay.tv_sec = 1;
-//  delay.tv_nsec = 500000000;
-//  nanosleep(&delay, NULL);
+//  MILLISLEEP(1000);
 
   vfeed.start();
   afeed.start();
   video->play();
   audio->play();
-  video->sync();
   audio->sync();
-
-  video->pause();
-      usleep(500000); // SYNC
-  video->sync();
-  video->unPause();
   video->sync();
+  resyncVideo();
 */
 
 // ------------------------------------------------------------------------------------------------
index 3ba19cb382e12934cacf3c4902b427b80a91b0cd..533917126bdaa5a9765ef80f0116c42e67164c30 100644 (file)
@@ -28,28 +28,10 @@ osd_font_t* Surface::font = &font_helvB18;
 Surface::Surface(int id)
 {
   if (id == SCREEN) screen = this;
-
-  fdOsd = Osd::getInstance()->getFD();
-  memset(&surface, 0, sizeof(osd_surface_t));
-  memset(&surface.sfc, 0, sizeof(stbgfx_sfc_t));
-  memset(&surface.map, 0, sizeof(stbgfx_map_t));
 }
 
 Surface::~Surface()
 {
-  for (int i = 0; i < 3; i++)
-  {
-    if (surface.base[i]) munmap(surface.base[i], surface.map.map[i].size);
-  }
-
-  int a;
-
-  a = ioctl(fdOsd, GFX_FB_SFC_UNMAP, surface.sfc.handle);
-  if (a) Log::getInstance()->log("Surface", Log::ERR, "Surface unmap failed");
-
-  a = ioctl(fdOsd, GFX_FB_SFC_FREE, surface.sfc.handle);
-  if (a) Log::getInstance()->log("Surface", Log::ERR, "Surface destroy failed");
-
 }
 
 Surface* Surface::getScreen()
@@ -57,264 +39,10 @@ Surface* Surface::getScreen()
   return screen;
 }
 
-int Surface::create(UINT width, UINT height)
-{
-  int r = 0;
-  int displayNumber = 0; // mvpmc iterates 0->15 till it gets one that works?
-
-  surface.sfc.width = width;
-  surface.sfc.height = height;
-  surface.sfc.flags = 0x3f1533;
-
-  surface.sfc.unknown = -1;
-
-//  r = ioctl(fdOsd, GFX_FB_SET_OSD, &displayNumber);
-//  if (r) return 0;
-
-  r = ioctl(fdOsd, GFX_FB_OSD_SURFACE, &displayNumber);
-  if (r) return 0;
-
-  r = ioctl(fdOsd, GFX_FB_SFC_ALLOC, &surface.sfc);
-  if (r) return 0;
-
-  surface.map.map[0].unknown = surface.sfc.handle;
-  r = ioctl(fdOsd, GFX_FB_MAP, &surface.map);
-  if (r) return 0;
-
-  surface.base[0] = (unsigned char *)mmap(NULL, surface.map.map[0].size, PROT_READ|PROT_WRITE, MAP_SHARED, fdOsd, surface.map.map[0].addr);
-  if (surface.base[0] == MAP_FAILED) return 0;
-
-  surface.base[1] = (unsigned char *)mmap(NULL, surface.map.map[1].size, PROT_READ|PROT_WRITE, MAP_SHARED, fdOsd, surface.map.map[1].addr);
-  if (surface.base[1] == MAP_FAILED) return 0;
-
-  surface.base[2] = (unsigned char *)mmap(NULL, surface.map.map[2].size, PROT_READ|PROT_WRITE, MAP_SHARED, fdOsd, surface.map.map[2].addr);
-  if (surface.base[2] == MAP_FAILED) return 0;
-
-//  surface.display.num = displayNumber;
-//  r = ioctl(fdOsd, GFX_FB_MOVE_DISPLAY, &surface.display);
-//  if (r) return 0;
-
-//  r = ioctl(fdOsd, GFX_FB_SET_DISPLAY, &surface.display);
-//  if (r) return 0;
-
-  return 1;
-}
-
-void Surface::display()
-{
-  unsigned long fb_descriptor[2];
-
-  fb_descriptor[0] = surface.sfc.handle;
-  fb_descriptor[1] = 1;
-
-  ioctl(fdOsd, GFX_FB_ATTACH, fb_descriptor);
-}
-
-unsigned long Surface::getSurfaceHandle()
-{
-  return surface.sfc.handle;
-}
-
-// ----------------------------------------------------------------------------
-
-// Now for the drawing functions
-
-/*
- * RGB to YUV conversion tables
- */
-int Surface::conv_YB[256];
-int Surface::conv_YG[256];
-int Surface::conv_YR[256];
-int Surface::conv_UB[256];
-int Surface::conv_UG[256];
-int Surface::conv_UR[256];
-int Surface::conv_VB[256];
-int Surface::conv_VG[256];
-int Surface::conv_VR[256];
-
-int Surface::conv_BY[256];
-int Surface::conv_GY[256];
-int Surface::conv_RY[256];
-int Surface::conv_BU[256];
-int Surface::conv_GU[256];
-int Surface::conv_RU[256];
-int Surface::conv_BV[256];
-int Surface::conv_GV[256];
-int Surface::conv_RV[256];
-
-/*
- * gfx_init() - initialize the RGB to YUV conversion tables
- */
-void Surface::initConversionTables(void)
-{
-  int i;
-
-  for (i=0; i<256; i++) {
-    conv_YB[i] = (int)(0.299 * (double)i);
-    conv_BY[i] = i;
-  }
-  for (i=0; i<256; i++) {
-    conv_YG[i] = (int)(0.587 * (double)i);
-    conv_GY[i] = i;
-  }
-  for (i=0; i<256; i++) {
-    conv_YR[i] = (int)(0.114 * (double)i);
-    conv_RY[i] = i;
-  }
-
-  for (i=0; i<256; i++) {
-    conv_UB[i] = (int)(0.5 * (double)i);
-    conv_BU[i] = (int)(1.732 * (i - 128));
-  }
-  for (i=0; i<256; i++) {
-    conv_UG[i] = (int)(-0.33126 * (double)i);
-    conv_GU[i] = (int)(-0.338 * (i - 128));
-  }
-  for (i=0; i<256; i++) {
-    conv_UR[i] = (int)(-0.16874 * (double)i);
-    conv_RU[i] = 0;
-  }
-
-  for (i=0; i<256; i++) {
-    conv_VB[i] = (int)(-0.08131 * (double)i);
-    conv_BV[i] = 0;
-  }
-  for (i=0; i<256; i++) {
-    conv_VG[i] = (int)(-0.41869 * (double)i);
-    conv_GV[i] = (int)(-0.698 * (i - 128));
-  }
-  for (i=0; i<256; i++) {
-    conv_VR[i] = (int)(0.5 * (double)i);
-    conv_RV[i] = (int)(1.370 * ((double)i - 128));
-  }
-}
-
-/*
- * rgb2yuv() - convert an RGB pixel to YUV
- */
- //inline me?
-void Surface::rgb2yuv(unsigned char r, unsigned char g, unsigned char b, unsigned char *y, unsigned char *u, unsigned char *v)
-{
-  int Y, U, V;
-
-  Y = conv_YB[b] + conv_YG[g] + conv_YR[r];
-  U = conv_UB[b] + conv_UG[g] + conv_UR[r] + 128;
-  V = conv_VB[b] + conv_VG[g] + conv_VR[r] + 128;
-
-  if (Y > 255)
-    Y = 255;
-  else if (Y < 0)
-    Y = 0;
-  if (U > 255)
-    U = 255;
-  else if (U < 0)
-    U = 0;
-  if (V > 255)
-    V = 255;
-  else if (V < 0)
-    V = 0;
-
-  *y = Y;
-  *u = U;
-  *v = V;
-}
-
-int Surface::fillblt(int x, int y, int width, int height, unsigned int c)
-{
-  osd_fillblt_t fblt;
-
-  fblt.handle = surface.sfc.handle;
-  fblt.x = x;
-  fblt.y = y;
-  fblt.width = width;
-  fblt.height = height;
-  fblt.colour = c;
-
-  return ioctl(fdOsd, GFX_FB_OSD_FILLBLT, &fblt);
-}
-
-void Surface::drawPixel(int x, int y, unsigned int c)
-{
-  int offset;
-  unsigned char r, g, b, a, Y, U, V;
-  unsigned int line, remainder;
-
-  if ((x >= (int)surface.sfc.width) || (y >= (int)surface.sfc.height))
-    return;
-
-  c2rgba(c, &r, &g, &b, &a);
-
-  rgb2yuv(r, g, b, &Y, &U, &V);
-
-  remainder = (surface.sfc.width % 4);
-  if (remainder == 0)
-    line = surface.sfc.width;
-  else
-    line = surface.sfc.width + (4 - remainder);
-
-  offset = (y * line) + x;
-
-  *(surface.base[0] + offset) = Y;
-  *(surface.base[1] + (offset & 0xfffffffe)) = U;
-  *(surface.base[1] + (offset & 0xfffffffe) + 1) = V;
-  *(surface.base[2] + offset) = a;
-
-}
-
-void Surface::drawHorzLine(int x1, int x2, int y, unsigned int c)
-{
-  fillblt(x1, y, x2-x1, 1, c);
-}
-
-void Surface::drawVertLine(int x, int y1, int y2, unsigned int c)
-{
-  fillblt(x, y1, 1, y2-y1, c);
-}
-
-
-  /* surface update to screen needs:
-  source x distance into this surface
-  source y distance into this surface
-  width of update
-  height of update
-  destination x on screen
-  destination y on screen
-  */
-int Surface::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
-{
-  return blt(fdOsd, surface.sfc.handle, sx, sy, w, h, screen->getSurfaceHandle(), dx, dy);
-}
-
-int Surface::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
-{
-  osd_bitblt_t fblt;
-  memset(&fblt, 0, sizeof(fblt));
-
-  fblt.dst_handle = dhandle;
-  fblt.dst_x = dx;
-  fblt.dst_y = dy;
-
-  fblt.src_handle = shandle;
-  fblt.src_x = sx;
-  fblt.src_y = sy;
-
-  fblt.width = width;
-  fblt.height = height;
-
-  fblt.u1 = 1;
-  fblt.u2 = 0;
-  fblt.u3 = 0x0f;
-
-  return ioctl(fd, GFX_FB_OSD_BITBLT, &fblt);
-}
-
-int Surface::drawText(char* text, int x, int y, int r, int g, int b)
+int Surface::drawText(char* text, int x, int y, ULONG rgba)
 {
   int h, n, i;
   int Y, X, cx;
-  unsigned long fg;
-
-  fg = rgba(r, g, b, 255);
 
   n = strlen(text);
   h = font->height;
@@ -334,7 +62,7 @@ int Surface::drawText(char* text, int x, int y, int r, int g, int b)
       {
         if ((character[Y] >> (32 - X)) & 0x1)
         {
-          drawPixel(x+X+cx, y+Y, fg);
+          drawPixel(x+X+cx, y+Y, rgba);
           pixels++;
         }
       }
@@ -344,7 +72,7 @@ int Surface::drawText(char* text, int x, int y, int r, int g, int b)
   return 1;
 }
 
-int Surface::drawTextRJ(char* text, int x, int y, int r, int g, int b)
+int Surface::drawTextRJ(char* text, int x, int y, ULONG rgba)
 {
   int i, n, w;
   w = 0;
@@ -359,10 +87,10 @@ int Surface::drawTextRJ(char* text, int x, int y, int r, int g, int b)
   x -= w;
 
   if (x < 0) return 0;
-  else return drawText(text, x, y, r, g, b);
+  else return drawText(text, x, y, rgba);
 }
 
-int Surface::drawTextCentre(char* text, int x, int y, int r, int g, int b)
+int Surface::drawTextCentre(char* text, int x, int y, ULONG rgba)
 {
   int i, n, w;
   w = 0;
@@ -377,7 +105,7 @@ int Surface::drawTextCentre(char* text, int x, int y, int r, int g, int b)
   x -= w / 2;
 
   if (x < 0) return 0;
-  else return drawText(text, x, y, r, g, b);
+  else return drawText(text, x, y, rgba);
 }
 
 int Surface::getCharWidth(char c)
@@ -389,139 +117,3 @@ int Surface::getFontHeight()
 {
   return font->spacing;
 }
-
-void Surface::screenShot(char* fileName)
-{
-  Log* logger = Log::getInstance();
-
-  FILE* outfile = fopen(fileName, "w");
-  if (outfile == NULL)
-  {
-    logger->log("Surface", Log::ERR, "Can't open JPEG");
-    return;
-  }
-  logger->log("Surface", Log::DEBUG, "File opened %u %u", surface.sfc.height, surface.sfc.width);
-
-  struct jpeg_compress_struct cinfo;
-  struct jpeg_error_mgr jerr;
-  cinfo.err = jpeg_std_error(&jerr);
-  jpeg_create_compress(&cinfo);
-  jpeg_stdio_dest(&cinfo, outfile);
-  cinfo.image_width = surface.sfc.width;
-  cinfo.image_height = surface.sfc.height;
-  cinfo.input_components = 3;
-  cinfo.in_color_space = JCS_RGB;
-  jpeg_set_defaults(&cinfo);
-  jpeg_start_compress(&cinfo, TRUE);
-
-
-  unsigned char row[surface.sfc.width * 3];
-  unsigned char* prow = (unsigned char*)&row;
-  unsigned char r, g, b;
-
-  while (cinfo.next_scanline < cinfo.image_height)
-  {
-    for(unsigned int i = 0; i < surface.sfc.width; i++)
-    {
-      readPixel(i, cinfo.next_scanline, &r, &g, &b);
-      row[i * 3] = r;
-      row[(i * 3) + 1] = g;
-      row[(i * 3) + 2] = b;
-    }
-    jpeg_write_scanlines(&cinfo, (JSAMPLE **)&prow, 1);
-  }
-
-  jpeg_finish_compress(&cinfo);
-  jpeg_destroy_compress(&cinfo);
-  fclose(outfile);
-  logger->log("Surface", Log::DEBUG, "Jpeg saved");
-}
-
-void Surface::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
-{
-  int offset;
-  unsigned char a, Y, U, V;
-  unsigned int line, remainder;
-
-  if (((unsigned int)x >= surface.sfc.width) || ((unsigned int)y >= surface.sfc.height)) return;
-
-  remainder = (surface.sfc.width % 4);
-  if (remainder == 0)
-    line = surface.sfc.width;
-  else
-    line = surface.sfc.width + (4 - remainder);
-
-  offset = (y * line) + x;
-
-  Y = *(surface.base[0] + offset);
-  U = *(surface.base[1] + (offset & 0xfffffffe));
-  V = *(surface.base[1] + (offset & 0xfffffffe) + 1);
-  a = *(surface.base[2] + offset);
-
-  yuv2rgb(Y, U, V, r, g, b);
-}
-
-void Surface::yuv2rgb(int y, int u, int v, unsigned char* pr, unsigned char* pg, unsigned char* pb)
-{
-   // from http://www.fourcc.org/index.php?http%3A//www.fourcc.org/fccyvrgb.php
-
-//   unsigned int pixel32;
-//   unsigned char *pixel = (unsigned char *)&pixel32;
-   int r, g, b;
-
-
-   /*
-     One formula I found:  (not the right one)
-
-     R = 1.164(Y - 16) + 1.596(Cr - 128)
-     G = 1.164(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128)
-     B = 1.164(Y - 16)                   + 2.018(Cb - 128)
-
-
-   r = (1.164 * (y - 16))
-      + (2.018 * (v - 128));
-   g = (1.164 * (y - 16))
-      - (0.813 * (u - 128))
-      - (0.391 * (v - 128));
-   b = (1.164 * (y - 16))
-      + (1.596 * (u - 128));
-
-
-     Another formula I found:  (seems to work)
-
-     R = Y + 1.370705 (V-128)
-     G = Y - 0.698001 (V-128) - 0.337633 (U-128)
-     B = Y + 1.732446 (U-128)
-   */
-
-   r = (int)( y + (1.370705 * (v-128)) );
-   g = (int)( y - (0.698001 * (v-128)) - (0.337633 * (u-128)) );
-   b = (int)( y + (1.732446 * (u-128)) );
-
-   // Even with proper conversion, some values still need clipping.
-   if (r > 255) r = 255;
-   if (g > 255) g = 255;
-   if (b > 255) b = 255;
-   if (r < 0) r = 0;
-   if (g < 0) g = 0;
-   if (b < 0) b = 0;
-
-   // Values only go from 0-220..  Why?
-//   pixel[0] = r * 220 / 256;
-//   pixel[1] = g * 220 / 256;
-//   pixel[2] = b * 220 / 256;
-//   pixel[3] = 0;
-
-   *pr = (unsigned char) (r * 220 / 256);
-   *pg = (unsigned char) (g * 220 / 256);
-   *pb = (unsigned char) (b * 220 / 256);
-
-   /* Debug
-   //printf("yuv2rgb(%i, %i, %i) -> %i, %i, %i  (0x%x)\n",
-    y, u, v,
-    pixel[0], pixel[1], pixel[2],
-    pixel32);
-   */
-
-//   return pixel32;
-}
index c44656d0717730ce100ce04f4f2fd8a9a5d17b68..66fb5febfa73f9c3a50dcbb2894974628c3fa816 100644 (file)
--- a/surface.h
+++ b/surface.h
 #define SURFACE_H
 
 #include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-
-// Structures for surface management
-
-typedef struct
-{
-  unsigned long num;
-  unsigned long unknown[4];
-  unsigned long width;
-  unsigned long height;
-  char unknown2;
-} stbgfx_display_t;
-
-typedef struct
-{
-  unsigned long unknown;
-  unsigned long win_unknown;
-  unsigned long addr;
-  unsigned long size;
-  unsigned long unknown2;
-  unsigned long width;
-  unsigned long height;
-  unsigned long unknown3;
-  unsigned long unknown4;
-  unsigned long width2;
-  unsigned long unknown5;
-  unsigned long unknown6;
-} stbgfx_map_item_t;
-
-typedef struct {
-  stbgfx_map_item_t map[3];
-  unsigned long other[2];
-} stbgfx_map_t;
-
-typedef struct
-{
-  unsigned long handle; /* surface handle */
-  unsigned long width;
-  unsigned long height;
-  unsigned long flags;
-  long unknown;   //unsigned long
-  unsigned long depth;  /* number of subplanes */
-} stbgfx_sfc_t;
-
-typedef struct
-{
-  stbgfx_display_t display;
-  stbgfx_map_t map;
-  stbgfx_sfc_t sfc;
-  unsigned char *base[3];
-} osd_surface_t;
-
-
-// Structures for surface drawing
-
-typedef struct
-{
-  unsigned long handle;
-  unsigned long x;
-  unsigned long y;
-  unsigned long width;
-  unsigned long height;
-  unsigned long colour;
-} osd_fillblt_t;
-
-typedef struct {
-  unsigned long dst_handle;
-  unsigned long dst_x;
-  unsigned long dst_y;
-  unsigned long width;
-  unsigned long height;
-  unsigned long src_handle;
-  unsigned long src_x;
-  unsigned long src_y;
-  unsigned long u1;
-  unsigned long u2;
-  unsigned char u3;
-} osd_bitblt_t;
+#include "defines.h"
+#include "log.h"
 
 // Font stuff
 
@@ -120,130 +41,39 @@ extern osd_font_t font_CaslonRoman_1_25;
 extern osd_font_t font_helvB24;
 extern osd_font_t font_helvB18;
 
-// Surface ioctls
-
-#define GFX_FB_SFC_ALLOC  _IOWR(0xfb,1,int*)
-#define GFX_FB_SFC_FREE   _IOW(0xfb,2,int)
-#define GFX_FB_MAP    _IOWR(0xfb,3,int*)
-#define GFX_FB_SFC_UNMAP  _IOW(0xfb,4,int)
-#define GFX_FB_SET_PAL_1  _IOWR(0xfb,5,int*)
-#define GFX_FB_SET_PAL_2  _IOW(0xfb,6,int*)
-#define GFX_FB_OSD_SURFACE  _IO(0xfb,7)
-#define GFX_FB_SFC_SET_SHARE  _IOW(0xfb,8,int)
-#define GFX_FB_OSD_CUR_SETATTR  _IOW(0xfb,9,int*)
-#define GFX_FB_ATTACH   _IOW(0xfb,11,int)
-#define GFX_FB_SFC_DETACH _IOW(0xfb,12,int*)
-#define GFX_FB_MOVE_DISPLAY _IOWR(0xfb,13,int)
-#define GFX_FB_SET_DISPLAY  _IOW(0xfb,14,int)
-#define GFX_FB_OSD_CUR_MOVE_1 _IOW(0xfb,15,int*)
-#define GFX_FB_OSD_CUR_MOVE_2 _IOW(0xfb,16,int)
-#define GFX_FB_SET_OSD    _IOW(0xfb,18,int)
-#define GFX_FB_SET_DISP_CTRL  _IOW(0xfb,21,int*)
-#define GFX_FB_GET_DISP_CTRL  _IOWR(0xfb,22,int*)
-#define GFX_FB_SET_VIS_DEV_CTL  _IOWR(0xfb,23,int*)
-#define GFX_FB_GET_VIS_DEV_CTL  _IOWR(0xfb,24,int*)
-#define GFX_FB_OSD_BITBLT _IOW(0xfb,51,osd_bitblt_t*)
-#define GFX_FB_OSD_FILLBLT  _IOW(0xfb,53,osd_fillblt_t*)
-#define GFX_FB_OSD_ADVFILLBLT _IOW(0xfb,54,osd_afillblt_t*)
-#define GFX_FB_OSD_BLEND  _IOW(0xfb,55,int*)
-#define GFX_FB_OSD_ADVBLEND _IOW(0xfb,56,int*)
-#define GFX_FB_OSD_RESIZE _IOW(0xfb,58,int*)
-#define GFX_FB_ENGINE_WAIT  _IOW(0xfb,60,int)
-#define GFX_FB_RESET_ENGINE _IO(0xfb,61)
-#define GFX_FB_SET_ENGINE_MODE  _IOW(0xfb,62,int)
-#define GFX_FB_GET_ENGINE_MODE  _IO(0xfb,63)
-#define GFX_FB_GET_SFC_INFO _IO(0xfb,64,int*)
-#define GFX_FB_OSD_SFC_CLIP _IOW(0xfb,65,osd_clip_rec_t*)
-#define GFX_FB_OSD_COLOURKEY  _IOW(0xfb,67,int*)
-#define GFX_FB_GET_SFC_PSEUDO _IOWR(0xfb,68,int*)
-
-extern "C"
-{
-  #include <jpeglib.h>
-}
-
-#include "defines.h"
-#include "log.h"
-
 class Surface
 {
   public:
     Surface(int id = 0);
-    ~Surface();
+    virtual ~Surface();
 
     static Surface* getScreen();
     static int getFontHeight();
+    int getCharWidth(char c);
 
-    int create(UINT width, UINT height);
-    void display();
-    unsigned long getSurfaceHandle();
+    int drawText(char* text, int x, int y, ULONG rgba);
+    int drawTextRJ(char* text, int x, int y, ULONG rgba);
+    int drawTextCentre(char* text, int x, int y, ULONG rgba);
 
-    int fillblt(int x, int y, int width, int height, unsigned int c);
-    void drawPixel(int x, int y, unsigned int c);
-    void drawHorzLine(int x1, int x2, int y, unsigned int c);
-    void drawVertLine(int x, int y1, int y2, unsigned int c);
-    int updateToScreen(int sx, int sy, int w, int h, int dx, int dy);
+    virtual int create(UINT width, UINT height)=0;
+    virtual void display()=0;
 
-    int drawText(char* text, int x, int y, int r, int g, int b);
-    int drawTextRJ(char* text, int x, int y, int r, int g, int b);
-    int drawTextCentre(char* text, int x, int y, int r, int g, int b);
-    int getCharWidth(char c);
-    void readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b);
-    void yuv2rgb(int y, int u, int v, unsigned char* pr, unsigned char* pg, unsigned char* pb);
-    void screenShot(char* fileName);
+    virtual int fillblt(int x, int y, int width, int height, unsigned int c)=0;
+    virtual void drawPixel(int x, int y, unsigned int c)=0;
+    virtual void drawHorzLine(int x1, int x2, int y, unsigned int c)=0;
+    virtual void drawVertLine(int x, int y1, int y2, unsigned int c)=0;
+    virtual int updateToScreen(int sx, int sy, int w, int h, int dx, int dy)=0;
+    virtual void readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)=0;
+    virtual void screenShot(char* fileName)=0;
 
-    static void initConversionTables();
-
-    static int blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy);
+    virtual int blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)=0;
 
     const static int SCREEN = 1;
     const static int BUFFER = 2;
 
-    // Implicit inlines
-    void c2rgba(unsigned long c, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
-    {
-      *a = (c & 0xff000000) >> 24;
-      *r = (c & 0x00ff0000) >> 16;
-      *g = (c & 0x0000ff00) >> 8;
-      *b = (c & 0x000000ff);
-    }
-
-    unsigned long rgba(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
-    {
-      return (a<<24) | (r<<16) | (g<<8) | b;
-
-    }
-
-  private:
+  protected:
     static Surface* screen;
     static osd_font_t* font;
-
-    int fdOsd;
-
-    osd_surface_t surface;
-
-    void rgb2yuv(unsigned char r, unsigned char g, unsigned char b, unsigned char *y, unsigned char *u, unsigned char *v);
-
-    static int conv_YB[256];
-    static int conv_YG[256];
-    static int conv_YR[256];
-    static int conv_UB[256];
-    static int conv_UG[256];
-    static int conv_UR[256];
-    static int conv_VB[256];
-    static int conv_VG[256];
-    static int conv_VR[256];
-
-    static int conv_BY[256];
-    static int conv_GY[256];
-    static int conv_RY[256];
-    static int conv_BU[256];
-    static int conv_GU[256];
-    static int conv_RU[256];
-    static int conv_BV[256];
-    static int conv_GV[256];
-    static int conv_RV[256];
-
 };
 
 #endif
diff --git a/surfacemvp.cc b/surfacemvp.cc
new file mode 100644 (file)
index 0000000..66626c0
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Portions copyright 2004 Jon Gettler
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "surfacemvp.h"
+#include "osd.h"
+
+SurfaceMVP::SurfaceMVP(int id)
+{
+  if (id == SCREEN) screen = this;
+
+  fdOsd = Osd::getInstance()->getFD();
+  memset(&surface, 0, sizeof(osd_surface_t));
+  memset(&surface.sfc, 0, sizeof(stbgfx_sfc_t));
+  memset(&surface.map, 0, sizeof(stbgfx_map_t));
+}
+
+SurfaceMVP::~SurfaceMVP()
+{
+  for (int i = 0; i < 3; i++)
+  {
+    if (surface.base[i]) munmap(surface.base[i], surface.map.map[i].size);
+  }
+
+  int a;
+
+  a = ioctl(fdOsd, GFX_FB_SFC_UNMAP, surface.sfc.handle);
+  if (a) Log::getInstance()->log("Surface", Log::ERR, "Surface unmap failed");
+
+  a = ioctl(fdOsd, GFX_FB_SFC_FREE, surface.sfc.handle);
+  if (a) Log::getInstance()->log("Surface", Log::ERR, "Surface destroy failed");
+
+}
+
+int SurfaceMVP::create(UINT width, UINT height)
+{
+  int r = 0;
+  int displayNumber = 0; // mvpmc iterates 0->15 till it gets one that works?
+
+  surface.sfc.width = width;
+  surface.sfc.height = height;
+  surface.sfc.flags = 0x3f1533;
+
+  surface.sfc.unknown = -1;
+
+//  r = ioctl(fdOsd, GFX_FB_SET_OSD, &displayNumber);
+//  if (r) return 0;
+
+  r = ioctl(fdOsd, GFX_FB_OSD_SURFACE, &displayNumber);
+  if (r) return 0;
+
+  r = ioctl(fdOsd, GFX_FB_SFC_ALLOC, &surface.sfc);
+  if (r) return 0;
+
+  surface.map.map[0].unknown = surface.sfc.handle;
+  r = ioctl(fdOsd, GFX_FB_MAP, &surface.map);
+  if (r) return 0;
+
+  surface.base[0] = (unsigned char *)mmap(NULL, surface.map.map[0].size, PROT_READ|PROT_WRITE, MAP_SHARED, fdOsd, surface.map.map[0].addr);
+  if (surface.base[0] == MAP_FAILED) return 0;
+
+  surface.base[1] = (unsigned char *)mmap(NULL, surface.map.map[1].size, PROT_READ|PROT_WRITE, MAP_SHARED, fdOsd, surface.map.map[1].addr);
+  if (surface.base[1] == MAP_FAILED) return 0;
+
+  surface.base[2] = (unsigned char *)mmap(NULL, surface.map.map[2].size, PROT_READ|PROT_WRITE, MAP_SHARED, fdOsd, surface.map.map[2].addr);
+  if (surface.base[2] == MAP_FAILED) return 0;
+
+//  surface.display.num = displayNumber;
+//  r = ioctl(fdOsd, GFX_FB_MOVE_DISPLAY, &surface.display);
+//  if (r) return 0;
+
+//  r = ioctl(fdOsd, GFX_FB_SET_DISPLAY, &surface.display);
+//  if (r) return 0;
+
+  return 1;
+}
+
+void SurfaceMVP::display()
+{
+  unsigned long fb_descriptor[2];
+
+  fb_descriptor[0] = surface.sfc.handle;
+  fb_descriptor[1] = 1;
+
+  ioctl(fdOsd, GFX_FB_ATTACH, fb_descriptor);
+}
+
+unsigned long SurfaceMVP::getSurfaceHandle()
+{
+  return surface.sfc.handle;
+}
+
+// ----------------------------------------------------------------------------
+
+// Now for the drawing functions
+
+/*
+ * RGB to YUV conversion tables
+ */
+int SurfaceMVP::conv_YB[256];
+int SurfaceMVP::conv_YG[256];
+int SurfaceMVP::conv_YR[256];
+int SurfaceMVP::conv_UB[256];
+int SurfaceMVP::conv_UG[256];
+int SurfaceMVP::conv_UR[256];
+int SurfaceMVP::conv_VB[256];
+int SurfaceMVP::conv_VG[256];
+int SurfaceMVP::conv_VR[256];
+
+int SurfaceMVP::conv_BY[256];
+int SurfaceMVP::conv_GY[256];
+int SurfaceMVP::conv_RY[256];
+int SurfaceMVP::conv_BU[256];
+int SurfaceMVP::conv_GU[256];
+int SurfaceMVP::conv_RU[256];
+int SurfaceMVP::conv_BV[256];
+int SurfaceMVP::conv_GV[256];
+int SurfaceMVP::conv_RV[256];
+
+/*
+ * gfx_init() - initialize the RGB to YUV conversion tables
+ */
+void SurfaceMVP::initConversionTables(void)
+{
+  int i;
+
+  for (i=0; i<256; i++) {
+    conv_YB[i] = (int)(0.299 * (double)i);
+    conv_BY[i] = i;
+  }
+  for (i=0; i<256; i++) {
+    conv_YG[i] = (int)(0.587 * (double)i);
+    conv_GY[i] = i;
+  }
+  for (i=0; i<256; i++) {
+    conv_YR[i] = (int)(0.114 * (double)i);
+    conv_RY[i] = i;
+  }
+
+  for (i=0; i<256; i++) {
+    conv_UB[i] = (int)(0.5 * (double)i);
+    conv_BU[i] = (int)(1.732 * (i - 128));
+  }
+  for (i=0; i<256; i++) {
+    conv_UG[i] = (int)(-0.33126 * (double)i);
+    conv_GU[i] = (int)(-0.338 * (i - 128));
+  }
+  for (i=0; i<256; i++) {
+    conv_UR[i] = (int)(-0.16874 * (double)i);
+    conv_RU[i] = 0;
+  }
+
+  for (i=0; i<256; i++) {
+    conv_VB[i] = (int)(-0.08131 * (double)i);
+    conv_BV[i] = 0;
+  }
+  for (i=0; i<256; i++) {
+    conv_VG[i] = (int)(-0.41869 * (double)i);
+    conv_GV[i] = (int)(-0.698 * (i - 128));
+  }
+  for (i=0; i<256; i++) {
+    conv_VR[i] = (int)(0.5 * (double)i);
+    conv_RV[i] = (int)(1.370 * ((double)i - 128));
+  }
+}
+
+/*
+ * rgb2yuv() - convert an RGB pixel to YUV
+ */
+ //inline me?
+void SurfaceMVP::rgb2yuv(unsigned char r, unsigned char g, unsigned char b, unsigned char *y, unsigned char *u, unsigned char *v)
+{
+  int Y, U, V;
+
+  Y = conv_YB[b] + conv_YG[g] + conv_YR[r];
+  U = conv_UB[b] + conv_UG[g] + conv_UR[r] + 128;
+  V = conv_VB[b] + conv_VG[g] + conv_VR[r] + 128;
+
+  if (Y > 255)
+    Y = 255;
+  else if (Y < 0)
+    Y = 0;
+  if (U > 255)
+    U = 255;
+  else if (U < 0)
+    U = 0;
+  if (V > 255)
+    V = 255;
+  else if (V < 0)
+    V = 0;
+
+  *y = Y;
+  *u = U;
+  *v = V;
+}
+
+int SurfaceMVP::fillblt(int x, int y, int width, int height, unsigned int c)
+{
+  osd_fillblt_t fblt;
+
+  fblt.handle = surface.sfc.handle;
+  fblt.x = x;
+  fblt.y = y;
+  fblt.width = width;
+  fblt.height = height;
+  fblt.colour = c;
+
+  return ioctl(fdOsd, GFX_FB_OSD_FILLBLT, &fblt);
+}
+
+void SurfaceMVP::drawPixel(int x, int y, unsigned int c)
+{
+  int offset;
+  unsigned char r, g, b, a, Y, U, V;
+  unsigned int line, remainder;
+
+  if ((x >= (int)surface.sfc.width) || (y >= (int)surface.sfc.height))
+    return;
+
+  c2rgba(c, &r, &g, &b, &a);
+
+  rgb2yuv(r, g, b, &Y, &U, &V);
+
+  remainder = (surface.sfc.width % 4);
+  if (remainder == 0)
+    line = surface.sfc.width;
+  else
+    line = surface.sfc.width + (4 - remainder);
+
+  offset = (y * line) + x;
+
+  *(surface.base[0] + offset) = Y;
+  *(surface.base[1] + (offset & 0xfffffffe)) = U;
+  *(surface.base[1] + (offset & 0xfffffffe) + 1) = V;
+  *(surface.base[2] + offset) = a;
+
+}
+
+void SurfaceMVP::drawHorzLine(int x1, int x2, int y, unsigned int c)
+{
+  fillblt(x1, y, x2-x1, 1, c);
+}
+
+void SurfaceMVP::drawVertLine(int x, int y1, int y2, unsigned int c)
+{
+  fillblt(x, y1, 1, y2-y1, c);
+}
+
+
+  /* surface update to screen needs:
+  source x distance into this surface
+  source y distance into this surface
+  width of update
+  height of update
+  destination x on screen
+  destination y on screen
+  */
+int SurfaceMVP::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
+{
+  return blt(fdOsd, surface.sfc.handle, sx, sy, w, h, ((SurfaceMVP*)screen)->getSurfaceHandle(), dx, dy);
+}
+
+int SurfaceMVP::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
+{
+  osd_bitblt_t fblt;
+  memset(&fblt, 0, sizeof(fblt));
+
+  fblt.dst_handle = dhandle;
+  fblt.dst_x = dx;
+  fblt.dst_y = dy;
+
+  fblt.src_handle = shandle;
+  fblt.src_x = sx;
+  fblt.src_y = sy;
+
+  fblt.width = width;
+  fblt.height = height;
+
+  fblt.u1 = 1;
+  fblt.u2 = 0;
+  fblt.u3 = 0x0f;
+
+  return ioctl(fd, GFX_FB_OSD_BITBLT, &fblt);
+}
+
+void SurfaceMVP::screenShot(char* fileName)
+{
+  Log* logger = Log::getInstance();
+
+  FILE* outfile = fopen(fileName, "w");
+  if (outfile == NULL)
+  {
+    logger->log("Surface", Log::ERR, "Can't open JPEG");
+    return;
+  }
+  logger->log("Surface", Log::DEBUG, "File opened %u %u", surface.sfc.height, surface.sfc.width);
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_compress(&cinfo);
+  jpeg_stdio_dest(&cinfo, outfile);
+  cinfo.image_width = surface.sfc.width;
+  cinfo.image_height = surface.sfc.height;
+  cinfo.input_components = 3;
+  cinfo.in_color_space = JCS_RGB;
+  jpeg_set_defaults(&cinfo);
+  jpeg_start_compress(&cinfo, TRUE);
+
+
+  unsigned char row[surface.sfc.width * 3];
+  unsigned char* prow = (unsigned char*)&row;
+  unsigned char r, g, b;
+
+  while (cinfo.next_scanline < cinfo.image_height)
+  {
+    for(unsigned int i = 0; i < surface.sfc.width; i++)
+    {
+      readPixel(i, cinfo.next_scanline, &r, &g, &b);
+      row[i * 3] = r;
+      row[(i * 3) + 1] = g;
+      row[(i * 3) + 2] = b;
+    }
+    jpeg_write_scanlines(&cinfo, (JSAMPLE **)&prow, 1);
+  }
+
+  jpeg_finish_compress(&cinfo);
+  jpeg_destroy_compress(&cinfo);
+  fclose(outfile);
+  logger->log("Surface", Log::DEBUG, "Jpeg saved");
+}
+
+void SurfaceMVP::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
+{
+  int offset;
+  unsigned char a, Y, U, V;
+  unsigned int line, remainder;
+
+  if (((unsigned int)x >= surface.sfc.width) || ((unsigned int)y >= surface.sfc.height)) return;
+
+  remainder = (surface.sfc.width % 4);
+  if (remainder == 0)
+    line = surface.sfc.width;
+  else
+    line = surface.sfc.width + (4 - remainder);
+
+  offset = (y * line) + x;
+
+  Y = *(surface.base[0] + offset);
+  U = *(surface.base[1] + (offset & 0xfffffffe));
+  V = *(surface.base[1] + (offset & 0xfffffffe) + 1);
+  a = *(surface.base[2] + offset);
+
+  yuv2rgb(Y, U, V, r, g, b);
+}
+
+void SurfaceMVP::yuv2rgb(int y, int u, int v, unsigned char* pr, unsigned char* pg, unsigned char* pb)
+{
+   // from http://www.fourcc.org/index.php?http%3A//www.fourcc.org/fccyvrgb.php
+
+//   unsigned int pixel32;
+//   unsigned char *pixel = (unsigned char *)&pixel32;
+   int r, g, b;
+
+
+   /*
+     One formula I found:  (not the right one)
+
+     R = 1.164(Y - 16) + 1.596(Cr - 128)
+     G = 1.164(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128)
+     B = 1.164(Y - 16)                   + 2.018(Cb - 128)
+
+
+   r = (1.164 * (y - 16))
+      + (2.018 * (v - 128));
+   g = (1.164 * (y - 16))
+      - (0.813 * (u - 128))
+      - (0.391 * (v - 128));
+   b = (1.164 * (y - 16))
+      + (1.596 * (u - 128));
+
+
+     Another formula I found:  (seems to work)
+
+     R = Y + 1.370705 (V-128)
+     G = Y - 0.698001 (V-128) - 0.337633 (U-128)
+     B = Y + 1.732446 (U-128)
+   */
+
+   r = (int)( y + (1.370705 * (v-128)) );
+   g = (int)( y - (0.698001 * (v-128)) - (0.337633 * (u-128)) );
+   b = (int)( y + (1.732446 * (u-128)) );
+
+   // Even with proper conversion, some values still need clipping.
+   if (r > 255) r = 255;
+   if (g > 255) g = 255;
+   if (b > 255) b = 255;
+   if (r < 0) r = 0;
+   if (g < 0) g = 0;
+   if (b < 0) b = 0;
+
+   // Values only go from 0-220..  Why?
+//   pixel[0] = r * 220 / 256;
+//   pixel[1] = g * 220 / 256;
+//   pixel[2] = b * 220 / 256;
+//   pixel[3] = 0;
+
+   *pr = (unsigned char) (r * 220 / 256);
+   *pg = (unsigned char) (g * 220 / 256);
+   *pb = (unsigned char) (b * 220 / 256);
+
+   /* Debug
+   //printf("yuv2rgb(%i, %i, %i) -> %i, %i, %i  (0x%x)\n",
+    y, u, v,
+    pixel[0], pixel[1], pixel[2],
+    pixel32);
+   */
+
+//   return pixel32;
+}
diff --git a/surfacemvp.h b/surfacemvp.h
new file mode 100644 (file)
index 0000000..79c4083
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Portions copyright 2004 Jon Gettler
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef SURFACEMVP_H
+#define SURFACEMVP_H
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+extern "C"
+{
+  #include <jpeglib.h>
+}
+
+#include "defines.h"
+#include "log.h"
+#include "surface.h"
+
+// Structures for surface management
+
+typedef struct
+{
+  unsigned long num;
+  unsigned long unknown[4];
+  unsigned long width;
+  unsigned long height;
+  char unknown2;
+} stbgfx_display_t;
+
+typedef struct
+{
+  unsigned long unknown;
+  unsigned long win_unknown;
+  unsigned long addr;
+  unsigned long size;
+  unsigned long unknown2;
+  unsigned long width;
+  unsigned long height;
+  unsigned long unknown3;
+  unsigned long unknown4;
+  unsigned long width2;
+  unsigned long unknown5;
+  unsigned long unknown6;
+} stbgfx_map_item_t;
+
+typedef struct {
+  stbgfx_map_item_t map[3];
+  unsigned long other[2];
+} stbgfx_map_t;
+
+typedef struct
+{
+  unsigned long handle; /* surface handle */
+  unsigned long width;
+  unsigned long height;
+  unsigned long flags;
+  long unknown;   //unsigned long
+  unsigned long depth;  /* number of subplanes */
+} stbgfx_sfc_t;
+
+typedef struct
+{
+  stbgfx_display_t display;
+  stbgfx_map_t map;
+  stbgfx_sfc_t sfc;
+  unsigned char *base[3];
+} osd_surface_t;
+
+
+// Structures for surface drawing
+
+typedef struct
+{
+  unsigned long handle;
+  unsigned long x;
+  unsigned long y;
+  unsigned long width;
+  unsigned long height;
+  unsigned long colour;
+} osd_fillblt_t;
+
+typedef struct {
+  unsigned long dst_handle;
+  unsigned long dst_x;
+  unsigned long dst_y;
+  unsigned long width;
+  unsigned long height;
+  unsigned long src_handle;
+  unsigned long src_x;
+  unsigned long src_y;
+  unsigned long u1;
+  unsigned long u2;
+  unsigned char u3;
+} osd_bitblt_t;
+
+// Surface ioctls
+
+#define GFX_FB_SFC_ALLOC  _IOWR(0xfb,1,int*)
+#define GFX_FB_SFC_FREE   _IOW(0xfb,2,int)
+#define GFX_FB_MAP    _IOWR(0xfb,3,int*)
+#define GFX_FB_SFC_UNMAP  _IOW(0xfb,4,int)
+#define GFX_FB_SET_PAL_1  _IOWR(0xfb,5,int*)
+#define GFX_FB_SET_PAL_2  _IOW(0xfb,6,int*)
+#define GFX_FB_OSD_SURFACE  _IO(0xfb,7)
+#define GFX_FB_SFC_SET_SHARE  _IOW(0xfb,8,int)
+#define GFX_FB_OSD_CUR_SETATTR  _IOW(0xfb,9,int*)
+#define GFX_FB_ATTACH   _IOW(0xfb,11,int)
+#define GFX_FB_SFC_DETACH _IOW(0xfb,12,int*)
+#define GFX_FB_MOVE_DISPLAY _IOWR(0xfb,13,int)
+#define GFX_FB_SET_DISPLAY  _IOW(0xfb,14,int)
+#define GFX_FB_OSD_CUR_MOVE_1 _IOW(0xfb,15,int*)
+#define GFX_FB_OSD_CUR_MOVE_2 _IOW(0xfb,16,int)
+#define GFX_FB_SET_OSD    _IOW(0xfb,18,int)
+#define GFX_FB_SET_DISP_CTRL  _IOW(0xfb,21,int*)
+#define GFX_FB_GET_DISP_CTRL  _IOWR(0xfb,22,int*)
+#define GFX_FB_SET_VIS_DEV_CTL  _IOWR(0xfb,23,int*)
+#define GFX_FB_GET_VIS_DEV_CTL  _IOWR(0xfb,24,int*)
+#define GFX_FB_OSD_BITBLT _IOW(0xfb,51,osd_bitblt_t*)
+#define GFX_FB_OSD_FILLBLT  _IOW(0xfb,53,osd_fillblt_t*)
+#define GFX_FB_OSD_ADVFILLBLT _IOW(0xfb,54,osd_afillblt_t*)
+#define GFX_FB_OSD_BLEND  _IOW(0xfb,55,int*)
+#define GFX_FB_OSD_ADVBLEND _IOW(0xfb,56,int*)
+#define GFX_FB_OSD_RESIZE _IOW(0xfb,58,int*)
+#define GFX_FB_ENGINE_WAIT  _IOW(0xfb,60,int)
+#define GFX_FB_RESET_ENGINE _IO(0xfb,61)
+#define GFX_FB_SET_ENGINE_MODE  _IOW(0xfb,62,int)
+#define GFX_FB_GET_ENGINE_MODE  _IO(0xfb,63)
+#define GFX_FB_GET_SFC_INFO _IO(0xfb,64,int*)
+#define GFX_FB_OSD_SFC_CLIP _IOW(0xfb,65,osd_clip_rec_t*)
+#define GFX_FB_OSD_COLOURKEY  _IOW(0xfb,67,int*)
+#define GFX_FB_GET_SFC_PSEUDO _IOWR(0xfb,68,int*)
+
+class SurfaceMVP : public Surface
+{
+  public:
+    SurfaceMVP(int id = 0);
+    ~SurfaceMVP();
+
+    int create(UINT width, UINT height);
+    void display();
+    unsigned long getSurfaceHandle();
+
+    int fillblt(int x, int y, int width, int height, unsigned int rgba);
+    void drawPixel(int x, int y, unsigned int c);
+    void drawHorzLine(int x1, int x2, int y, unsigned int c);
+    void drawVertLine(int x, int y1, int y2, unsigned int c);
+    int updateToScreen(int sx, int sy, int w, int h, int dx, int dy);
+    void readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b);
+    void screenShot(char* fileName);
+
+    static void initConversionTables();
+
+    int blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy);
+
+  private:
+    int fdOsd;
+    osd_surface_t surface;
+
+    void yuv2rgb(int y, int u, int v, unsigned char* pr, unsigned char* pg, unsigned char* pb);
+    void rgb2yuv(unsigned char r, unsigned char g, unsigned char b, unsigned char *y, unsigned char *u, unsigned char *v);
+
+    // Implicit inlines
+    void c2rgba(unsigned long c, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
+    {
+      *a = (c & 0xff000000) >> 24;
+      *r = (c & 0x00ff0000) >> 16;
+      *g = (c & 0x0000ff00) >> 8;
+      *b = (c & 0x000000ff);
+    }
+
+    static int conv_YB[256];
+    static int conv_YG[256];
+    static int conv_YR[256];
+    static int conv_UB[256];
+    static int conv_UG[256];
+    static int conv_UR[256];
+    static int conv_VB[256];
+    static int conv_VG[256];
+    static int conv_VR[256];
+
+    static int conv_BY[256];
+    static int conv_GY[256];
+    static int conv_RY[256];
+    static int conv_BU[256];
+    static int conv_GU[256];
+    static int conv_RU[256];
+    static int conv_BV[256];
+    static int conv_GV[256];
+    static int conv_RV[256];
+
+};
+
+#endif
diff --git a/surfacewin.cc b/surfacewin.cc
new file mode 100644 (file)
index 0000000..d17eb24
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Portions copyright 2004 Jon Gettler
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "surfacewin.h"
+#include "osd.h"
+
+SurfaceWin::SurfaceWin(int id)
+{
+}
+
+SurfaceWin::~SurfaceWin()
+{
+}
+
+int SurfaceWin::create(UINT width, UINT height)
+{
+  return 0;
+}
+
+void SurfaceWin::display()
+{
+}
+
+int SurfaceWin::fillblt(int x, int y, int width, int height, unsigned int c)
+{
+  return 0;
+}
+
+void SurfaceWin::drawPixel(int x, int y, unsigned int c)
+{
+}
+
+void SurfaceWin::drawHorzLine(int x1, int x2, int y, unsigned int c)
+{
+}
+
+void SurfaceWin::drawVertLine(int x, int y1, int y2, unsigned int c)
+{
+}
+
+int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
+{
+  return 0;
+}
+
+int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
+{
+  return 0;
+}
+
+void SurfaceWin::screenShot(char* fileName)
+{
+}
+
+void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
+{
+}
diff --git a/surfacewin.h b/surfacewin.h
new file mode 100644 (file)
index 0000000..6b7eb70
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+    Copyright 2004-2005 Chris Tallon
+    Portions copyright 2004 Jon Gettler
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef SURFACEWIN_H
+#define SURFACEWIN_H
+
+#include "defines.h"
+#include "log.h"
+#include "surface.h"
+
+class SurfaceWin : public Surface
+{
+  public:
+    SurfaceWin(int id = 0);
+    ~SurfaceWin();
+
+    int create(UINT width, UINT height);
+    void display();
+
+    int fillblt(int x, int y, int width, int height, unsigned int c);
+    void drawPixel(int x, int y, unsigned int c);
+    void drawHorzLine(int x1, int x2, int y, unsigned int c);
+    void drawVertLine(int x, int y1, int y2, unsigned int c);
+    int updateToScreen(int sx, int sy, int w, int h, int dx, int dy);
+    void readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b);
+    void screenShot(char* fileName);
+
+    int blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy);
+
+  private:
+};
+
+#endif
diff --git a/vepg.cc b/vepg.cc
index 9aaca603a8fbfa2e9b29b94c6fb8370d7135a277..a27a05febc30de8d899d764fd6546fd8cfb90832 100644 (file)
--- a/vepg.cc
+++ b/vepg.cc
@@ -197,7 +197,7 @@ void VEpg::draw()
   // Display the status and key stuff at the bottom\r
   int keyx = chanListbox.getOffsetX();\r
   int keyy = chanListbox.getOffsetY() + chanListbox.getHeight() + 2;\r
-  surface->fillblt(keyx, keyy, 605, Surface::getFontHeight() * 2 + 14, surface->rgba(100, 100, 100, 255));\r
+  rectangle(keyx, keyy, 605, Surface::getFontHeight() * 2 + 14, Colour(100, 100, 100, 255));\r
 
   WSymbol w;\r
   w.setSurface(surface);\r
@@ -220,32 +220,32 @@ void VEpg::draw()
 \r
   drawText(tr("OK"), keyx + 18, keyy + 20, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 72, keyy + 4, 104, Surface::getFontHeight() + 2, surface->rgba(200, 0, 0, 255));\r
+  rectangle(keyx + 72, keyy + 4, 104, Surface::getFontHeight() + 2, Colour(200, 0, 0, 255));\r
   drawText(tr("Page up"), keyx + 74, keyy + 5, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 72, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, surface->rgba(0, 200, 0, 255));\r
+  rectangle(keyx + 72, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, Colour(0, 200, 0, 255));\r
   drawText(tr("Page down"), keyx + 74, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 180, keyy + 4, 104, Surface::getFontHeight() + 2, surface->rgba(200, 200, 0, 255));\r
+  rectangle(keyx + 180, keyy + 4, 104, Surface::getFontHeight() + 2, Colour(200, 200, 0, 255));\r
   drawText(tr("-24 hours"), keyx + 182, keyy + 5, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 180, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, surface->rgba( 0, 0, 200, 255));\r
+  rectangle(keyx + 180, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, Colour(0, 0, 200, 255));\r
   drawText(tr("+24 hours"), keyx + 182, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 290, keyy + 4, 180, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
+  rectangle(keyx + 290, keyy + 4, 180, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255));\r
   drawText(tr("Guide / Back: Close"), keyx + 292 , keyy + 5, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 290, keyy + Surface::getFontHeight() + 8, 180, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
+  rectangle(keyx + 290, keyy + Surface::getFontHeight() + 8, 180, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255));\r
   Colour red = Colour(130, 0, 0);\r
   drawText(tr("Rec: Set timer"), keyx + 292, keyy + Surface::getFontHeight() + 9, red);\r
 \r
-  surface->fillblt(keyx + 474, keyy + 4, 128, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
+  rectangle(keyx + 474, keyy + 4, 128, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255));\r
   w.nextSymbol = WSymbol::PLAY;\r
   w.setSurfaceOffset(keyx + 476, keyy + 5);\r
   w.draw();\r
   drawText(tr("Sel channel"), keyx + 496, keyy + 5, Colour::LIGHTTEXT);\r
 \r
-  surface->fillblt(keyx + 474, keyy + Surface::getFontHeight() + 8, 128, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
+  rectangle(keyx + 474, keyy + Surface::getFontHeight() + 8, 128, Surface::getFontHeight() + 2, Colour(180, 180, 180, 255));\r
   drawText(tr("Go: Preview"), keyx + 476, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT);\r
 \r
   // Draw all the dynamic data\r
@@ -425,19 +425,19 @@ void VEpg::drawgrid() // redraws grid and select programme
   drawTextRJ(timeString, timex - 10, timey, Colour::LIGHTTEXT); // print date\r
   strftime(timeString, 19, "%H:%M", tms);\r
   drawText(timeString, timex, timey, Colour::LIGHTTEXT); // print left time\r
-  surface->fillblt(155, timey + Surface::getFontHeight(), 2, 7, surface->rgba(255, 255, 255, 255));\r
+  rectangle(155, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255));\r
   t = t + 3600;\r
   tms = localtime(&t);\r
   strftime(timeString, 19, "%H:%M", tms);\r
   drawText(timeString, timex + 180, timey, Colour::LIGHTTEXT); // print middle time\r
-  surface->fillblt(335, timey + Surface::getFontHeight(), 2, 7, surface->rgba(255, 255, 255, 255));\r
+  rectangle(335, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255));\r
   t = t + 3600;\r
   tms = localtime(&t);\r
   strftime(timeString, 19, "%H:%M", tms);\r
   drawText(timeString, timex + 360, timey, Colour::LIGHTTEXT); // print right time\r
-  surface->fillblt(515, timey + Surface::getFontHeight(), 2, 7, surface->rgba(255, 255, 255, 255));\r
+  rectangle(515, timey + Surface::getFontHeight(), 2, 7, Colour(255, 255, 255, 255));\r
   // pointer to selTime\r
-  surface->fillblt(155 + (selTime - ltime) / 20, timey + Surface::getFontHeight(), 2, 7, surface->rgba(255, 50, 50, 255));\r
+  rectangle(155 + (selTime - ltime) / 20, timey + Surface::getFontHeight(), 2, 7, Colour(255, 50, 50, 255));\r
 \r
   // TODO should the above two comditional statements be combined to avoid calling updateEventList() twice?\r
   Event* event;\r
@@ -587,7 +587,7 @@ void VEpg::paintCell(Event* event, int yOffset, Colour bg, Colour fg)
   }\r
   if (w > 155 + WINDOW_WIDTH * MINUTE_SCALE - x)\r
     w = 155 + WINDOW_WIDTH * MINUTE_SCALE -x; // limit cells to RHS of window\r
-  surface->fillblt(x, y, w, h, surface->rgba(bg.red, bg.green, bg.blue, bg.alpha));\r
+  rectangle(x, y, w, h, bg);\r
   char* tt = new char[strlen(event->title) + 1];\r
   strcpy (tt, event->title);\r
   int textWidth = 0;\r
@@ -606,7 +606,7 @@ void VEpg::paintCell(Event* event, int yOffset, Colour bg, Colour fg)
   {\r
     strncpy(tT, tt, textWidth - 1);\r
     tT[textWidth - 1] =  '\0';\r
-    surface->drawText(tT, x+2, y, fg.red, fg.green, fg.blue);\r
+    surface->drawText(tT, x+2, y, fg.rgba());\r
   }\r
   delete tT;\r
 \r
diff --git a/view.cc b/view.cc
index efeb07b969aae08c3938e439730611f72a216a04..962069f7b0636ca11a40e09fa48b36ebe62fc30e 100644 (file)
--- a/view.cc
+++ b/view.cc
@@ -50,7 +50,7 @@ bool View::create(UINT w, UINT h)
   area.w = w;
   area.h = h;
 
-  surface = new Surface();
+  surface = new Surface_TYPE();
   return surface->create(area.w, area.h);
 }
 
index 0ddc9201c2d08e17e283121c2a8ce0ff8089d96e..99e88c6671cc73be9f566764777d7784fb648bd7 100644 (file)
@@ -330,13 +330,6 @@ void ViewMan::boxSplit(Region r, int start, int end, int direction, RegionList&
   }
 }
 
-// TEMP
-void ViewMan::drawBlack(Region& r)
-{
-  Surface* surface = Surface::getScreen();
-  surface->fillblt(r.x, r.y, r.w, r.h, surface->rgba(0, 0, 0, 255));
-}
-
 /////////////////////////////////////////////////////////////////////////////
 // END NEW STUFF
 /////////////////////////////////////////////////////////////////////////////
index 6fc3d2b42d896915f2c1ab51da4e2dfbc00469c9..5b4643a88e4000e071bf8278fdb3a0187ab84d74 100644 (file)
--- a/viewman.h
+++ b/viewman.h
@@ -72,7 +72,6 @@ class ViewMan : public MessageQueue
     void deleteView(int z);
     void repaintRevealed(int x, Region r);
     void boxSplit(Region r, int start, int end, int direction, RegionList& rl);
-    void drawBlack(Region& r);
 };
 
 #endif