Mercurial > sdl-ios-xcode
diff src/video/photon/SDL_photon_render.c @ 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 | 7f684f249ec9 |
children | 90935231e9b6 |
line wrap: on
line diff
--- 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: */