changeset 3375:dd105b317335

Continue working on 2D support for Photon/QNX.
author Mike Gorchak <lestat@i.com.ua>
date Sat, 10 Oct 2009 20:15:20 +0000
parents 725b16784e96
children 106a409ceeef
files src/video/photon/SDL_photon.c src/video/photon/SDL_photon_render.c src/video/photon/SDL_photon_render.h
diffstat 3 files changed, 584 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/src/video/photon/SDL_photon.c	Sat Oct 10 18:37:35 2009 +0000
+++ b/src/video/photon/SDL_photon.c	Sat Oct 10 20:15:20 2009 +0000
@@ -44,7 +44,7 @@
 #if defined(SDL_VIDEO_OPENGL_ES)
 #include "../qnxgf/SDL_gf_pixelfmt.h"
 
-   /* If GF driver is not compiled in, include some of usefull functions */
+/* If GF driver is not compiled in, include some of usefull functions */
 #if !defined(SDL_VIDEO_DRIVER_QNXGF)
 #include "../qnxgf/SDL_gf_pixelfmt.c"
 #endif /* SDL_VIDEO_DRIVER_QNXGF */
@@ -54,7 +54,7 @@
 #if defined(SDL_VIDEO_OPENGL_ES)
 #include "../qnxgf/SDL_gf_opengles.h"
 
-   /* If GF driver is not compiled in, include some of usefull functions */
+/* If GF driver is not compiled in, include some of usefull functions */
 #if !defined(SDL_VIDEO_DRIVER_QNXGF)
 #include "../qnxgf/SDL_gf_opengles.c"
 #endif /* SDL_VIDEO_DRIVER_QNXGF */
@@ -137,7 +137,7 @@
     /* VIA UniChrome graphics driver (devg-unichrome.so)    */
     {"unichrome", SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D}
     ,
-    /* VESA unaccelerated gfx driver (devg-vesa.so)         */
+    /* VESA unaccelerated gfx driver (devg-vesabios.so)     */
     {"vesa", SDL_PHOTON_UNACCELERATED | SDL_PHOTON_UNACCELERATED_3D}
     ,
     /* VmWare graphics driver (devg-volari.so)              */
@@ -155,7 +155,7 @@
 static int
 photon_available(void)
 {
-    int status;
+    int32_t status;
 
     /* Check if Photon was initialized before */
     if (photon_initialized == SDL_FALSE) {
@@ -194,7 +194,7 @@
 {
     SDL_VideoDevice *device;
     SDL_VideoData *phdata;
-    int status;
+    int32_t status;
 
     /* Check if photon could be initialized */
     status = photon_available();
@@ -883,6 +883,13 @@
     PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_STATE, Pt_TRUE,
              Ph_WM_STATE_ISALTKEY);
 
+    /* Special case, do not handle maximize events, if window can't be resized */
+    if ((window->flags & SDL_WINDOW_RESIZABLE) != SDL_WINDOW_RESIZABLE)
+    {
+       PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE,
+                Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_RESIZE);
+    }
+
     /* Set window dimension */
     winsize.w = window->w;
     winsize.h = window->h;
@@ -1305,7 +1312,7 @@
     if (phdata->gfinitialized != SDL_TRUE) {
         SDL_SetError
             ("Photon: GF initialization failed, no OpenGL ES support");
-        return NULL;
+        return -1;
     }
 
     /* Check if OpenGL ES library is specified for GF driver */
@@ -1918,6 +1925,7 @@
         (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
     PhRect_t dst_rect;
     PhRect_t src_rect;
+    int32_t status;
 
     if (phdata->gfinitialized != SDL_TRUE) {
         SDL_SetError
@@ -1951,6 +1959,17 @@
     src_rect.lr.x = window->w - 1;
     src_rect.lr.y = window->h - 1;
 
+    /* Check if current device is not the same as target */
+    if (phdata->current_device_id != didata->device_id) {
+        /* Set target device as default for Pd and Pg functions */
+        status = PdSetTargetDevice(NULL, phdata->rid[didata->device_id]);
+        if (status != 0) {
+            SDL_SetError("Photon: Can't set default target device\n");
+            return;
+        }
+        phdata->current_device_id = didata->device_id;
+    }
+
     /* Blit OpenGL ES pixmap surface directly to window region */
     PgFFlush(Ph_START_DRAW);
     PgSetRegionCx(PhDCGetCurrent(), PtWidgetRid(wdata->window));
@@ -2324,12 +2343,8 @@
                                 if ((wdata != NULL) && (window != NULL)) {
                                     /* Check if window uses OpenGL ES */
                                     if (wdata->uses_gles == SDL_TRUE) {
-                                        PhRect_t dst_rect;
-                                        PhRect_t src_rect;
-
                                         /* Cycle through each rectangle */
-                                        for (it = 0; it < event->num_rects;
-                                             it++) {
+                                        for (it = 0; it < event->num_rects; it++) {
                                             /* Blit OpenGL ES pixmap surface directly to window region */
                                             PgFFlush(Ph_START_DRAW);
                                             PgSetRegionCx(PhDCGetCurrent(),
@@ -2345,8 +2360,14 @@
                                             PgWaitHWIdle();
                                         }
                                     } else {
-                                        /* Normal window */
-                                        /* TODO: update the damaged rectangles */
+                                        /* Cycle through each rectangle */
+                                        for (it = 0; it < event->num_rects;
+                                             it++) {
+                                            /* Blit 2D pixmap surface directly to window region */
+                                            _photon_update_rectangles(window->renderer, &rects[it]);
+                                        }
+                                        PgFlush();
+                                        PgWaitHWIdle();
                                     }
                                 }
 
@@ -2385,10 +2406,19 @@
                                         PgFFlush(Ph_DONE_DRAW);
                                         PgWaitHWIdle();
                                     } else {
-                                        /* Normal window */
-                                        /* TODO: update the damaged rectangles */
+                                        PhRect_t rect;
 
                                         /* We need to redraw entire window */
+                                        rect.ul.x = 0;
+                                        rect.ul.y = 0;
+                                        rect.lr.x = window->w - 1;
+                                        rect.lr.y = window->h - 1;
+
+                                        /* Blit 2D pixmap surface directly to window region */
+                                        PgFFlush(Ph_START_DRAW);
+                                        _photon_update_rectangles(window->renderer, &rect);
+                                        PgFFlush(Ph_DONE_DRAW);
+                                        PgWaitHWIdle();
                                     }
                                 }
                             }
@@ -2693,9 +2723,16 @@
                         case Ph_WM_MAX:
                             {
                                 if (window != NULL) {
-                                    SDL_SendWindowEvent(window->id,
-                                                        SDL_WINDOWEVENT_MAXIMIZED,
-                                                        0, 0);
+                                    if ((window->flags & SDL_WINDOW_RESIZABLE)==SDL_WINDOW_RESIZABLE)
+                                    {
+                                       SDL_SendWindowEvent(window->id,
+                                                           SDL_WINDOWEVENT_MAXIMIZED,
+                                                           0, 0);
+                                    }
+                                    else
+                                    {
+                                       /* otherwise ignor the resize events */
+                                    }
                                 }
                             }
                             break;
--- a/src/video/photon/SDL_photon_render.c	Sat Oct 10 18:37:35 2009 +0000
+++ b/src/video/photon/SDL_photon_render.c	Sat Oct 10 20:15:20 2009 +0000
@@ -68,6 +68,8 @@
 static void photon_dirtytexture(SDL_Renderer * renderer,
                                 SDL_Texture * texture, int numrects,
                                 const SDL_Rect * rects);
+static int photon_setdrawcolor(SDL_Renderer * renderer);
+static int photon_setdrawblendmode(SDL_Renderer * renderer);
 static int photon_renderpoint(SDL_Renderer * renderer, int x, int y);
 static int photon_renderline(SDL_Renderer * renderer, int x1, int y1, int x2,
                              int y2);
@@ -80,6 +82,8 @@
                                   SDL_Texture * texture);
 static void photon_destroyrenderer(SDL_Renderer * renderer);
 
+static int _photon_recreate_surfaces(SDL_Renderer * renderer);
+
 SDL_RenderDriver photon_renderdriver = {
     photon_createrenderer,
     {
@@ -92,18 +96,15 @@
       SDL_TEXTUREMODULATE_ALPHA),
      (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
       SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
-     (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_SLOW),
-     13,
-     {
-      SDL_PIXELFORMAT_INDEX8,
+     (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_SLOW |
+      SDL_TEXTURESCALEMODE_FAST | SDL_TEXTURESCALEMODE_BEST),
+     10,
+     {SDL_PIXELFORMAT_INDEX8,
       SDL_PIXELFORMAT_RGB555,
       SDL_PIXELFORMAT_RGB565,
+      SDL_PIXELFORMAT_RGB24,
       SDL_PIXELFORMAT_RGB888,
-      SDL_PIXELFORMAT_BGR888,
       SDL_PIXELFORMAT_ARGB8888,
-      SDL_PIXELFORMAT_RGBA8888,
-      SDL_PIXELFORMAT_ABGR8888,
-      SDL_PIXELFORMAT_BGRA8888,
       SDL_PIXELFORMAT_YV12,
       SDL_PIXELFORMAT_YUY2,
       SDL_PIXELFORMAT_UYVY,
@@ -150,6 +151,8 @@
     renderer->LockTexture = photon_locktexture;
     renderer->UnlockTexture = photon_unlocktexture;
     renderer->DirtyTexture = photon_dirtytexture;
+    renderer->SetDrawColor = photon_setdrawcolor;
+    renderer->SetDrawBlendMode = photon_setdrawblendmode;
     renderer->RenderPoint = photon_renderpoint;
     renderer->RenderLine = photon_renderline;
     renderer->RenderFill = photon_renderfill;
@@ -168,8 +171,6 @@
         renderer->info.flags &= ~(SDL_RENDERER_ACCELERATED);
     }
 
-    rdata->window = window;
-
     /* Check if upper level requested synchronization on vsync signal */
     if ((flags & SDL_RENDERER_PRESENTVSYNC) == SDL_RENDERER_PRESENTVSYNC) {
         rdata->enable_vsync = SDL_TRUE;
@@ -214,6 +215,13 @@
         }
     }
 
+    /* Create new graphics context */
+    if (rdata->gc==NULL)
+    {
+       rdata->gc=PgCreateGC(0);
+       PgDefaultGC(rdata->gc);
+    }
+
     return renderer;
 }
 
@@ -228,28 +236,347 @@
 }
 
 /****************************************************************************/
-/* SDL render interface                                                     */
+/* Render helper functions                                                  */
 /****************************************************************************/
-static int
-photon_displaymodechanged(SDL_Renderer * renderer)
+
+static int _photon_recreate_surfaces(SDL_Renderer * renderer)
 {
     SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+    SDL_VideoDisplay *display = NULL;
+    SDL_DisplayData *didata = NULL;
+    SDL_Window *window = NULL;
+    SDL_WindowData *wdata = NULL;
+    SDL_VideoData *phdata = NULL;
+    uint32_t allocate_task=SDL_PHOTON_SURFTYPE_UNKNOWN;
+    int32_t status;
 
-    /* Remove all allocated surfaces, they are no more valid */
+    /* Obtain window and display structures */
+    window=SDL_GetWindowFromID(renderer->window);
+    wdata=(SDL_WindowData*)window->driverdata;
+    display=SDL_GetDisplayFromWindow(window);
+    didata=(SDL_DisplayData *) display->driverdata;
+    phdata=(SDL_VideoData *) display->device->driverdata;
+
+    /* Check if it is OpenGL ES window */
+    if ((window->flags & SDL_WINDOW_OPENGL) == SDL_WINDOW_OPENGL) {
+        /* If so, do not waste surfaces */
+        rdata->surfaces_type=SDL_PHOTON_SURFTYPE_UNKNOWN;
+        return 0;
+    }
+
+    if (rdata->surfaces_type==SDL_PHOTON_SURFTYPE_UNKNOWN)
+    {
+       /* Try to allocate offscreen surfaces */
+       allocate_task=SDL_PHOTON_SURFTYPE_OFFSCREEN;
+    }
+    else
+    {
+       uint32_t it;
+
+       if (rdata->surfaces_type==SDL_PHOTON_SURFTYPE_OFFSCREEN)
+       {
+          /* Create offscreen surfaces */
+          allocate_task=SDL_PHOTON_SURFTYPE_OFFSCREEN;
+
+          /* Destroy current surfaces */
+          for (it=0; it<SDL_PHOTON_MAX_SURFACES; it++)
+          {
+             if (rdata->osurfaces[it] != NULL)
+             {
+                PhDCRelease(rdata->osurfaces[it]);
+                rdata->osurfaces[it] = NULL;
+             }
+          }
+       }
+       else
+       {
+          if (rdata->surfaces_type==SDL_PHOTON_SURFTYPE_PHIMAGE)
+          {
+             /* Create shared phimage surfaces */
+             allocate_task=SDL_PHOTON_SURFTYPE_PHIMAGE;
+
+             /* Destroy current surfaces */
+             for (it=0; it<SDL_PHOTON_MAX_SURFACES; it++)
+             {
+                if (rdata->pcontexts[it]!=NULL)
+                {
+                   PmMemReleaseMC(rdata->pcontexts[it]);
+                   rdata->pcontexts[it]=NULL;
+                }
+                if (rdata->psurfaces[it]!=NULL)
+                {
+                   if (rdata->psurfaces[it]->palette!=NULL)
+                   {
+                      SDL_free(rdata->psurfaces[it]->palette);
+                      rdata->psurfaces[it]->palette=NULL;
+                   }
+                   /* Destroy shared memory for PhImage_t */
+                   PgShmemDestroy(rdata->psurfaces[it]->image);
+                   rdata->psurfaces[it]->image=NULL;
+                   SDL_free(rdata->psurfaces[it]);
+                   rdata->psurfaces[it]=NULL;
+                }
+             }
+          }
+       }
+    }
+
+    /* Check if current device is not the same as target */
+    if (phdata->current_device_id != didata->device_id) {
+        /* Set target device as default for Pd and Pg functions */
+        status = PdSetTargetDevice(NULL, phdata->rid[didata->device_id]);
+        if (status != 0) {
+            SDL_SetError("Photon: Can't set default target device\n");
+            return -1;
+        }
+        phdata->current_device_id = didata->device_id;
+    }
+
+    switch (allocate_task)
+    {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            {
+               int32_t it;
+               int32_t jt;
+
+               /* Try the hardware accelerated offscreen surfaces first */
+               for (it=0; it<rdata->surfaces_count; it++)
+               {
+                  rdata->osurfaces[it]=PdCreateOffscreenContext(0, window->w, window->h,
+                  Pg_OSC_MEM_LINEAR_ACCESSIBLE |
+                  /* in case if 2D acceleration is not available use CPU optimized surfaces */
+                  Pg_OSC_MEM_HINT_CPU_READ | Pg_OSC_MEM_HINT_CPU_WRITE |
+                  /* in case if 2D acceleration is available use it */
+                  Pg_OSC_MEM_2D_WRITABLE | Pg_OSC_MEM_2D_READABLE);
+
+                  /* If we can't create an offscreen surface, then fallback to software */
+                  if (rdata->osurfaces[it]==NULL)
+                  {
+                     /* Destroy previously allocated surface(s) */
+                     for (jt = it - 1; jt > 0; jt--)
+                     {
+                        PhDCRelease(rdata->osurfaces[jt]);
+                        rdata->osurfaces[jt] = NULL;
+                     }
+                     break;
+                  }
+               }
 
-    /* TODO: Add video mode change detection and new parameters detection */
+               /* Check if all required surfaces have been created */
+               if (rdata->osurfaces[0]!=NULL)
+               {
+                  rdata->surfaces_type=SDL_PHOTON_SURFTYPE_OFFSCREEN;
+                  /* exit from switch if surfaces have been created */
+                  break;
+               }
+               else
+               {
+                  /* else fall through to software phimage surface allocation */
+               }
+            }
+            /* fall through */
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            {
+               int32_t it;
+               int32_t jt;
+               uint32_t image_pfmt=photon_sdl_to_image_pixelformat(didata->current_mode.format);
+
+               /* Try to allocate the software surfaces in shared memory */
+               for (it=0; it<rdata->surfaces_count; it++)
+               {
+                  /* If this surface with palette, create a palette space */
+                  if (image_pfmt==Pg_IMAGE_PALETTE_BYTE)
+                  {
+                     rdata->psurfaces[it]=PhCreateImage(NULL, window->w, window->h,
+                        image_pfmt, NULL, 256, 1);
+                  }
+                  else
+                  {
+                     rdata->psurfaces[it]=PhCreateImage(NULL, window->w, window->h,
+                        image_pfmt, NULL, 0, 1);
+                  }
+
+                  if (rdata->psurfaces[it]!=NULL)
+                  {
+                     PhPoint_t translation={0, 0};
+                     PhDim_t   dimension={window->w, window->h};
+
+                     /* Create memory context for PhImage_t */
+                     rdata->pcontexts[it]=PmMemCreateMC(rdata->psurfaces[it], &dimension, &translation);
+                  }
+
+                  if ((rdata->psurfaces[it]==NULL) || (rdata->pcontexts[it]==NULL))
+                  {
+                     /* Destroy previously allocated surface(s) */
+                     for (jt = it - 1; jt > 0; jt--)
+                     {
+                        if (rdata->pcontexts[jt]!=NULL)
+                        {
+                           PmMemReleaseMC(rdata->pcontexts[it]);
+                           rdata->pcontexts[jt]=NULL;
+                        }
+                        if (rdata->psurfaces[jt]!=NULL)
+                        {
+                           if (rdata->psurfaces[jt]->palette!=NULL)
+                           {
+                              SDL_free(rdata->psurfaces[jt]->palette);
+                              rdata->psurfaces[jt]->palette=NULL;
+                           }
+                           /* Destroy shared memory for PhImage_t */
+                           PgShmemDestroy(rdata->psurfaces[jt]->image);
+                           rdata->psurfaces[jt]->image=NULL;
+                           SDL_free(rdata->psurfaces[jt]);
+                           rdata->psurfaces[jt] = NULL;
+                        }
+                     }
+                     break;
+                  }
+               }
+
+               /* Check if all required surfaces have been created */
+               if (rdata->psurfaces[0]!=NULL)
+               {
+                  rdata->surfaces_type=SDL_PHOTON_SURFTYPE_PHIMAGE;
+               }
+               else
+               {
+                  rdata->surfaces_type=SDL_PHOTON_SURFTYPE_UNKNOWN;
+               }
+            }
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            {
+               /* do nothing with surface allocation */
+               rdata->surfaces_type=SDL_PHOTON_SURFTYPE_UNKNOWN;
+            }
+            break;
+    }
+
+    /* Check if one of two allocation scheme was successful */
+    if (rdata->surfaces_type==SDL_PHOTON_SURFTYPE_UNKNOWN)
+    {
+       SDL_SetError("Photon: primary surface(s) allocation failure");
+       return -1;
+    }
+
+    /* Store current surface dimensions */
+    rdata->window_width=window->w;
+    rdata->window_height=window->h;
+
+    /* If current copy/flip scheme is single buffer, then set initial parameters */
+    if ((renderer->info.flags & SDL_RENDERER_SINGLEBUFFER)==SDL_RENDERER_SINGLEBUFFER)
+    {
+       rdata->surface_visible_idx = 0;
+       rdata->surface_render_idx = 0;
+    }
+
+    /* If current copy/flip scheme is double buffer, then set initial parameters */
+    if ((renderer->info.flags & SDL_RENDERER_PRESENTFLIP2)==SDL_RENDERER_PRESENTFLIP2)
+    {
+       rdata->surface_visible_idx = 0;
+       rdata->surface_render_idx = 1;
+    }
+
+    /* If current copy/flip scheme is triple buffer, then set initial parameters */
+    if ((renderer->info.flags & SDL_RENDERER_PRESENTFLIP3)==SDL_RENDERER_PRESENTFLIP3)
+    {
+       rdata->surface_visible_idx = 0;
+       rdata->surface_render_idx = 1;
+    }
+
+    switch (rdata->surfaces_type)
+    {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgSetGCCx(rdata->osurfaces[rdata->surface_render_idx], rdata->gc);
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgSetGCCx(rdata->pcontexts[rdata->surface_render_idx], rdata->gc);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+    }
 
     return 0;
 }
 
+int _photon_update_rectangles(SDL_Renderer* renderer, PhRect_t* rect)
+{
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+   SDL_Window *window = window=SDL_GetWindowFromID(renderer->window);
+   SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
+   PhPoint_t src_point;
+
+   /* If currently single buffer is in use, we have to flush all data */
+   if (rdata->surface_render_idx==rdata->surface_visible_idx)
+   {
+      /* Flush all undrawn graphics data to surface */
+      switch (rdata->surfaces_type)
+      {
+          case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+               PgFlushCx(rdata->osurfaces[rdata->surface_visible_idx]);
+               PgWaitHWIdle();
+               break;
+          case SDL_PHOTON_SURFTYPE_PHIMAGE:
+               PmMemFlush(rdata->pcontexts[rdata->surface_visible_idx], rdata->psurfaces[rdata->surface_visible_idx]);
+               break;
+          case SDL_PHOTON_SURFTYPE_UNKNOWN:
+               return;
+      }
+   }
+
+   PgSetRegionCx(PhDCGetCurrent(), PtWidgetRid(wdata->window));
+
+   src_point.x = rect->ul.x;
+   src_point.y = rect->ul.y;
+
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgContextBlit(rdata->osurfaces[rdata->surface_visible_idx], rect, NULL, rect);
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgDrawPhImageRectv(&src_point, rdata->psurfaces[rdata->surface_visible_idx], rect, 0);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+   }
+}
+
+/****************************************************************************/
+/* SDL render interface                                                     */
+/****************************************************************************/
+
 static int
 photon_activaterenderer(SDL_Renderer * renderer)
 {
-    SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
-    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(rdata->window);
-    SDL_DisplayData *didata = (SDL_DisplayData *) display->driverdata;
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+   SDL_Window *window = SDL_GetWindowFromID(renderer->window);
+   SDL_WindowData *wdata = (SDL_WindowData *)window->driverdata;
+
+   if ((rdata->window_width!=window->w) || (rdata->window_height!=window->h))
+   {
+      return _photon_recreate_surfaces(renderer);
+   }
 
-    return 0;
+   switch (rdata->surfaces_type)
+   {
+      case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+           PgSetGCCx(rdata->osurfaces[rdata->surface_render_idx], rdata->gc);
+           break;
+      case SDL_PHOTON_SURFTYPE_PHIMAGE:
+           PgSetGCCx(rdata->pcontexts[rdata->surface_render_idx], rdata->gc);
+           break;
+      case SDL_PHOTON_SURFTYPE_UNKNOWN:
+           break;
+   }
+
+   return 0;
+}
+
+static int
+photon_displaymodechanged(SDL_Renderer * renderer)
+{
+    return _photon_recreate_surfaces(renderer);
 }
 
 static int
@@ -269,7 +596,6 @@
 
     /* Set texture driver data */
     texture->driverdata = tdata;
-
 }
 
 static int
@@ -336,18 +662,79 @@
 }
 
 static int
+photon_setdrawcolor(SDL_Renderer * renderer)
+{
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgSetFillColorCx(rdata->gc, PgRGB(renderer->r, renderer->g, renderer->b));
+            PgSetStrokeColorCx(rdata->gc, PgRGB(renderer->r, renderer->g, renderer->b));
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+   }
+}
+
+static int
+photon_setdrawblendmode(SDL_Renderer * renderer)
+{
+}
+
+static int
 photon_renderpoint(SDL_Renderer * renderer, int x, int y)
 {
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgDrawIPixelCx(rdata->osurfaces[rdata->surface_render_idx], x, y);
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgDrawIPixelCx(rdata->pcontexts[rdata->surface_render_idx], x, y);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+   }
 }
 
 static int
 photon_renderline(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
 {
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgDrawILineCx(rdata->osurfaces[rdata->surface_render_idx], x1, y1, x2, y2);
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgDrawILineCx(rdata->pcontexts[rdata->surface_render_idx], x1, y1, x2, y2);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+   }
 }
 
 static int
 photon_renderfill(SDL_Renderer * renderer, const SDL_Rect * rect)
 {
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgDrawIRectCx(rdata->osurfaces[rdata->surface_render_idx], rect->x, rect->y, rect->w+rect->x-1, rect->h+rect->y-1, Pg_DRAW_FILL);
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgDrawIRectCx(rdata->pcontexts[rdata->surface_render_idx], rect->x, rect->y, rect->w+rect->x-1, rect->h+rect->y-1, Pg_DRAW_FILL);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+   }
 }
 
 static int
@@ -359,6 +746,53 @@
 static void
 photon_renderpresent(SDL_Renderer * renderer)
 {
+   SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+   SDL_Window *window = window=SDL_GetWindowFromID(renderer->window);
+   SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
+   PhRect_t src_rect;
+   PhPoint_t src_point;
+
+   /* Flush all undrawn graphics data to surface */
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgFlushCx(rdata->osurfaces[rdata->surface_render_idx]);
+            PgWaitHWIdle();
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PmMemFlush(rdata->pcontexts[rdata->surface_render_idx], rdata->psurfaces[rdata->surface_render_idx]);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            return;
+   }
+
+   PgFFlush(Ph_START_DRAW);
+   PgSetRegionCx(PhDCGetCurrent(), PtWidgetRid(wdata->window));
+
+   /* Set blit area */
+   src_rect.ul.x = 0;
+   src_rect.ul.y = 0;
+   src_rect.lr.x = rdata->window_width - 1;
+   src_rect.lr.y = rdata->window_height - 1;
+
+   src_point.x = 0;
+   src_point.y = 0;
+
+   switch (rdata->surfaces_type)
+   {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            PgContextBlit(rdata->osurfaces[rdata->surface_render_idx], &src_rect, NULL, &src_rect);
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            PgDrawPhImagev(&src_point, rdata->psurfaces[rdata->surface_render_idx], 0);
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            break;
+   }
+
+   /* finish blit */
+   PgFFlush(Ph_DONE_DRAW);
+   PgWaitHWIdle();
 }
 
 static void
@@ -370,8 +804,64 @@
 photon_destroyrenderer(SDL_Renderer * renderer)
 {
     SDL_RenderData *rdata = (SDL_RenderData *) renderer->driverdata;
+    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
+    SDL_WindowData *wdata = (SDL_WindowData *)window->driverdata;
     uint32_t it;
 
+    /* Destroy graphics context */
+    if (rdata->gc!=NULL)
+    {
+       PgDestroyGC(rdata->gc);
+       rdata->gc=NULL;
+    }
+
+    switch (rdata->surfaces_type)
+    {
+       case SDL_PHOTON_SURFTYPE_OFFSCREEN:
+            {
+               /* Destroy current surfaces */
+               for (it=0; it<SDL_PHOTON_MAX_SURFACES; it++)
+               {
+                  if (rdata->osurfaces[it] != NULL)
+                  {
+                     PhDCRelease(rdata->osurfaces[it]);
+                     rdata->osurfaces[it] = NULL;
+                  }
+               }
+            }
+            break;
+       case SDL_PHOTON_SURFTYPE_PHIMAGE:
+            {
+               /* Destroy current surfaces */
+               for (it=0; it<SDL_PHOTON_MAX_SURFACES; it++)
+               {
+                  if (rdata->pcontexts[it]!=NULL)
+                  {
+                     PmMemReleaseMC(rdata->pcontexts[it]);
+                     rdata->pcontexts[it]=NULL;
+                  }
+                  if (rdata->psurfaces[it]!=NULL)
+                  {
+                     if (rdata->psurfaces[it]->palette!=NULL)
+                     {
+                        SDL_free(rdata->psurfaces[it]->palette);
+                        rdata->psurfaces[it]->palette=NULL;
+                     }
+                     /* Destroy shared memory for PhImage_t */
+                     PgShmemDestroy(rdata->psurfaces[it]->image);
+                     rdata->psurfaces[it]->image=NULL;
+                     SDL_free(rdata->psurfaces[it]);
+                     rdata->psurfaces[it]=NULL;
+                  }
+               }
+            }
+            break;
+       case SDL_PHOTON_SURFTYPE_UNKNOWN:
+            {
+               /* nothing to do */
+            }
+            break;
+    }
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/photon/SDL_photon_render.h	Sat Oct 10 18:37:35 2009 +0000
+++ b/src/video/photon/SDL_photon_render.h	Sat Oct 10 20:15:20 2009 +0000
@@ -30,16 +30,27 @@
 #include "../SDL_sysvideo.h"
 
 #include <Ph.h>
+#include <photon/PhRender.h>
 
 #define SDL_PHOTON_MAX_SURFACES 3
 
+#define SDL_PHOTON_SURFTYPE_UNKNOWN    0x00000000
+#define SDL_PHOTON_SURFTYPE_OFFSCREEN  0x00000001
+#define SDL_PHOTON_SURFTYPE_PHIMAGE    0x00000002
+
 typedef struct SDL_RenderData
 {
-    SDL_Window *window;         /* SDL window type                    */
-    SDL_bool enable_vsync;      /* VSYNC flip synchronization enable  */
-    uint32_t surface_visible_idx;       /* Index of visible surface     */
-    uint32_t surface_render_idx;        /* Index of render surface      */
-    uint32_t surfaces_count;    /* Amount of allocated surfaces */
+    SDL_bool enable_vsync;              /* VSYNC flip synchronization enable  */
+    uint32_t surface_visible_idx;       /* Index of visible surface           */
+    uint32_t surface_render_idx;        /* Index of render surface            */
+    uint32_t surfaces_count;            /* Amount of allocated surfaces       */
+    uint32_t surfaces_type;             /* Type of allocated surfaces         */
+    uint32_t window_width;              /* Last active window width           */
+    uint32_t window_height;             /* Last active window height          */
+    PhGC_t* gc;                         /* Graphics context                   */
+    PdOffscreenContext_t* osurfaces[SDL_PHOTON_MAX_SURFACES];
+    PhImage_t* psurfaces[SDL_PHOTON_MAX_SURFACES];
+    PmMemoryContext_t* pcontexts[SDL_PHOTON_MAX_SURFACES];
 } SDL_RenderData;
 
 typedef struct SDL_TextureData
@@ -48,6 +59,9 @@
 
 extern void photon_addrenderdriver(_THIS);
 
+/* Helper function, which redraws the backbuffer */
+int _photon_update_rectangles(SDL_Renderer* renderer, PhRect_t* rect);
+
 #endif /* __SDL_PHOTON_RENDER_H__ */
 
 /* vi: set ts=4 sw=4 expandtab: */