Mercurial > sdl-ios-xcode
diff src/video/directfb/SDL_DirectFB_render.c @ 5202:164f20ba08eb
Updated the DirectFB support, from Couriersud
attached is a working directfb driver diff which works with the current
changes. There are a number of changes around it as well, e.g.
configure.in.
The directfb renderdriver right now still depends on a some "includes"
from src/video/directfb. That's why it is not yet moved to the new
render folder.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 05 Feb 2011 16:07:10 -0800 |
parents | fb424691cfc7 |
children | 58265e606e4e |
line wrap: on
line diff
--- a/src/video/directfb/SDL_DirectFB_render.c Sat Feb 05 16:02:30 2011 -0800 +++ b/src/video/directfb/SDL_DirectFB_render.c Sat Feb 05 16:07:10 2011 -0800 @@ -18,47 +18,74 @@ Sam Lantinga slouken@libsdl.org - - SDL1.3 implementation by couriersud@arcor.de - + + SDL1.3 DirectFB driver by couriersud@arcor.de + */ -#include "SDL_config.h" +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_window.h" +#include "SDL_DirectFB_modes.h" -#include "SDL_DirectFB_video.h" -#include "SDL_DirectFB_render.h" -#include "../SDL_yuv_sw_c.h" +#include "SDL_DirectFB_shape.h" + +#include "../SDL_sysvideo.h" +#include "../../render/SDL_sysrender.h" +//#include "../SDL_rect_c.h" +//#include "../SDL_yuv_sw_c.h" /* the following is not yet tested ... */ #define USE_DISPLAY_PALETTE (0) + +#define SDL_DFB_RENDERERDATA(rend) DirectFB_RenderData *renddata = ((rend) ? (DirectFB_RenderData *) (rend)->driverdata : NULL) + + /* GDI renderer implementation */ static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags); -static int DirectFB_DisplayModeChanged(SDL_Renderer * renderer); -static int DirectFB_ActivateRenderer(SDL_Renderer * renderer); +static void DirectFB_ActivateRenderer(SDL_Renderer * renderer); static int DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, void **pixels, int *pitch); +static int DirectFB_SetTexturePalette(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Color * colors, + int firstcolor, int ncolors); +static int DirectFB_GetTexturePalette(SDL_Renderer * renderer, + SDL_Texture * texture, + SDL_Color * colors, + int firstcolor, int ncolors); +static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, + SDL_Texture * texture); +static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, + SDL_Texture * texture); static int DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch); static int DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, int markDirty, + const SDL_Rect * rect, void **pixels, int *pitch); static void DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); static void DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects, const SDL_Rect * rects); +static int DirectFB_SetDrawBlendMode(SDL_Renderer * renderer); static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count); static int DirectFB_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, int count); +static int DirectFB_RenderDrawRects(SDL_Renderer * renderer, + const SDL_Rect ** rects, int count); static int DirectFB_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count); static int DirectFB_RenderCopy(SDL_Renderer * renderer, @@ -69,6 +96,11 @@ static void DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); static void DirectFB_DestroyRenderer(SDL_Renderer * renderer); +static int DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, void * pixels, int pitch); +static int DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, const void * pixels, int pitch); + #define SDL_DFB_WINDOWSURFACE(win) IDirectFBSurface *destsurf = ((DFB_WindowData *) ((win)->driverdata))->surface; @@ -77,20 +109,16 @@ { "directfb", (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED), - 12, + /* (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR | + SDL_TEXTUREMODULATE_ALPHA), + (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | + SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD), + (SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST | + SDL_SCALEMODE_SLOW | SDL_SCALEMODE_BEST),*/ + 0, { - SDL_PIXELFORMAT_RGB332, - SDL_PIXELFORMAT_RGB555, - SDL_PIXELFORMAT_RGB565, - SDL_PIXELFORMAT_RGB888, - SDL_PIXELFORMAT_ARGB8888, - SDL_PIXELFORMAT_ARGB4444, - SDL_PIXELFORMAT_ARGB1555, - SDL_PIXELFORMAT_RGB24, - SDL_PIXELFORMAT_YV12, - SDL_PIXELFORMAT_IYUV, - SDL_PIXELFORMAT_YUY2, - SDL_PIXELFORMAT_UYVY}, + /* formats filled in later */ + }, 0, 0} }; @@ -99,7 +127,6 @@ { SDL_Window *window; DFBSurfaceFlipFlags flipflags; - int isyuvdirect; int size_changed; int lastBlendMode; DFBSurfaceBlittingFlags blitFlags; @@ -112,8 +139,11 @@ Uint32 format; void *pixels; int pitch; - SDL_VideoDisplay *display; - SDL_DirtyRectList dirty; + IDirectFBPalette *palette; + int isDirty; + + SDL_VideoDisplay *display; /* only for yuv textures */ + #if (DFB_VERSION_ATLEAST(1,2,0)) DFBSurfaceRenderOptions render_options; #endif @@ -135,7 +165,12 @@ /* Drawing primitive ? */ if (!data) return 0; + + return (DFB_PIXELFORMAT_HAS_ALPHA(DirectFB_SDLToDFBPixelFormat(data->format)) ? 1 : 0); +#if 0 switch (data->format) { + case SDL_PIXELFORMAT_INDEX4LSB: + case SDL_PIXELFORMAT_INDEX4MSB: case SDL_PIXELFORMAT_ARGB4444: case SDL_PIXELFORMAT_ARGB1555: case SDL_PIXELFORMAT_ARGB8888: @@ -143,10 +178,11 @@ case SDL_PIXELFORMAT_ABGR8888: case SDL_PIXELFORMAT_BGRA8888: case SDL_PIXELFORMAT_ARGB2101010: - return 1; + return 1; default: return 0; } +#endif } static void @@ -165,6 +201,14 @@ SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE)); SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ZERO)); break; +#if 0 + case SDL_BLENDMODE_MASK: + data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL; + data->drawFlags = DSDRAW_BLEND; + SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA)); + SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA)); + break; +#endif case SDL_BLENDMODE_BLEND: data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL; data->drawFlags = DSDRAW_BLEND; @@ -183,19 +227,74 @@ SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE)); SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ONE)); break; + case SDL_BLENDMODE_MOD: + data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL; + data->drawFlags = DSDRAW_BLEND; + //SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_DESTCOLOR)); + //SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ZERO)); + //data->glBlendFunc(GL_ZERO, GL_SRC_COLOR); + SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ZERO)); + SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_SRCCOLOR)); + + break; } data->lastBlendMode = blendMode; } } -void -DirectFB_AddRenderDriver(_THIS) +static int +DisplayPaletteChanged(void *userdata, SDL_Palette * palette) { +#if USE_DISPLAY_PALETTE + DirectFB_RenderData *data = (DirectFB_RenderData *) userdata; + SDL_DFB_WINDOWSURFACE(data->window); + IDirectFBPalette *surfpal; + int i; + int ncolors; + DFBColor entries[256]; - for (i = 0; i < _this->num_displays; ++i) { - SDL_AddRenderDriver(&_this->displays[i], &DirectFB_RenderDriver); + SDL_DFB_CHECKERR(destsurf->GetPalette(destsurf, &surfpal)); + + /* FIXME: number of colors */ + ncolors = (palette->ncolors < 256 ? palette->ncolors : 256); + + for (i = 0; i < ncolors; ++i) { + entries[i].r = palette->colors[i].r; + entries[i].g = palette->colors[i].g; + entries[i].b = palette->colors[i].b; + entries[i].a = palette->colors[i].unused; } + SDL_DFB_CHECKERR(surfpal->SetEntries(surfpal, entries, ncolors, 0)); + return 0; + error: +#else + SDL_Unsupported(); +#endif + return -1; +} + +static void +DirectFB_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) +{ + SDL_DFB_RENDERERDATA(renderer); + + if (event->event == SDL_WINDOWEVENT_RESIZED) { + /* Rebind the context to the window area and update matrices */ + //SDL_CurrentContext = NULL; + //data->updateSize = SDL_TRUE; + renddata->size_changed = SDL_TRUE; + } +} + +int +DirectFB_RenderClear(SDL_Renderer * renderer) +{ + SDL_DFB_RENDERERDATA(renderer); + + DirectFB_ActivateRenderer(renderer); + + return 0; } SDL_Renderer * @@ -205,35 +304,53 @@ SDL_VideoDisplay *display = window->display; SDL_Renderer *renderer = NULL; DirectFB_RenderData *data = NULL; - char *p; + DFBSurfaceCapabilities scaps; + //char *p; - SDL_DFB_CALLOC(renderer, 1, sizeof(*renderer)); - SDL_DFB_CALLOC(data, 1, sizeof(*data)); + SDL_DFB_ALLOC_CLEAR(renderer, sizeof(*renderer)); + SDL_DFB_ALLOC_CLEAR(data, sizeof(*data)); - renderer->DisplayModeChanged = DirectFB_DisplayModeChanged; - renderer->ActivateRenderer = DirectFB_ActivateRenderer; + renderer->WindowEvent = DirectFB_WindowEvent; renderer->CreateTexture = DirectFB_CreateTexture; - renderer->QueryTexturePixels = DirectFB_QueryTexturePixels; + renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod; + renderer->SetTextureColorMod = DirectFB_SetTextureColorMod; + renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode; renderer->UpdateTexture = DirectFB_UpdateTexture; renderer->LockTexture = DirectFB_LockTexture; + renderer->RenderClear = DirectFB_RenderClear; renderer->UnlockTexture = DirectFB_UnlockTexture; - renderer->DirtyTexture = DirectFB_DirtyTexture; renderer->RenderDrawPoints = DirectFB_RenderDrawPoints; renderer->RenderDrawLines = DirectFB_RenderDrawLines; + /* SetDrawColor - no needed */ renderer->RenderFillRects = DirectFB_RenderFillRects; /* RenderDrawEllipse - no reference implementation yet */ /* RenderFillEllipse - no reference implementation yet */ renderer->RenderCopy = DirectFB_RenderCopy; renderer->RenderPresent = DirectFB_RenderPresent; - /* RenderReadPixels is difficult to implement */ - /* RenderWritePixels is difficult to implement */ + + /* FIXME: Yet to be tested */ + renderer->RenderReadPixels = DirectFB_RenderReadPixels; + //renderer->RenderWritePixels = DirectFB_RenderWritePixels; + renderer->DestroyTexture = DirectFB_DestroyTexture; renderer->DestroyRenderer = DirectFB_DestroyRenderer; + +#if 0 + renderer->QueryTexturePixels = DirectFB_QueryTexturePixels; + renderer->SetTexturePalette = DirectFB_SetTexturePalette; + renderer->GetTexturePalette = DirectFB_GetTexturePalette; + renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode; + renderer->DirtyTexture = DirectFB_DirtyTexture; + renderer->SetDrawBlendMode = DirectFB_SetDrawBlendMode; + renderer->RenderDrawRects = DirectFB_RenderDrawRects; +#endif + renderer->info = DirectFB_RenderDriver.info; renderer->window = window; /* SDL window */ renderer->driverdata = data; - renderer->info.flags = SDL_RENDERER_ACCELERATED; + renderer->info.flags = + SDL_RENDERER_ACCELERATED; data->window = window; @@ -245,10 +362,26 @@ } else data->flipflags |= DSFLIP_ONSYNC; - data->isyuvdirect = 0; /* default is off! */ - p = SDL_getenv(DFBENV_USE_YUV_DIRECT); - if (p) - data->isyuvdirect = atoi(p); + SDL_DFB_CHECKERR(windata->surface-> + GetCapabilities(windata->surface, &scaps)); + +#if 0 + if (scaps & DSCAPS_DOUBLE) + renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; + else if (scaps & DSCAPS_TRIPLE) + renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; + else + renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER; +#endif + + DirectFB_SetSupportedPixelFormats(&renderer->info); + +#if 0 + /* Set up a palette watch on the display palette */ + if (display->palette) { + SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data); + } +#endif return renderer; @@ -258,58 +391,7 @@ return NULL; } -static DFBSurfacePixelFormat -SDLToDFBPixelFormat(Uint32 format) -{ - switch (format) { - case SDL_PIXELFORMAT_RGB332: - return DSPF_RGB332; - case SDL_PIXELFORMAT_RGB555: - return DSPF_ARGB1555; - case SDL_PIXELFORMAT_ARGB4444: - return DSPF_ARGB4444; - case SDL_PIXELFORMAT_ARGB1555: - return DSPF_ARGB1555; - case SDL_PIXELFORMAT_RGB565: - return DSPF_RGB16; - case SDL_PIXELFORMAT_RGB24: - return DSPF_RGB24; - case SDL_PIXELFORMAT_RGB888: - return DSPF_RGB32; - case SDL_PIXELFORMAT_ARGB8888: - return DSPF_ARGB; - case SDL_PIXELFORMAT_YV12: - return DSPF_YV12; /* Planar mode: Y + V + U (3 planes) */ - case SDL_PIXELFORMAT_IYUV: - return DSPF_I420; /* Planar mode: Y + U + V (3 planes) */ - case SDL_PIXELFORMAT_YUY2: - return DSPF_YUY2; /* Packed mode: Y0+U0+Y1+V0 (1 plane) */ - case SDL_PIXELFORMAT_UYVY: - return DSPF_UYVY; /* Packed mode: U0+Y0+V0+Y1 (1 plane) */ - case SDL_PIXELFORMAT_YVYU: - return DSPF_UNKNOWN; /* Packed mode: Y0+V0+Y1+U0 (1 plane) */ -#if (DFB_VERSION_ATLEAST(1,2,0)) - case SDL_PIXELFORMAT_RGB444: - return DSPF_RGB444; -#endif - case SDL_PIXELFORMAT_BGR24: - return DSPF_UNKNOWN; - case SDL_PIXELFORMAT_BGR888: - return DSPF_UNKNOWN; - case SDL_PIXELFORMAT_RGBA8888: - return DSPF_UNKNOWN; - case SDL_PIXELFORMAT_ABGR8888: - return DSPF_UNKNOWN; - case SDL_PIXELFORMAT_BGRA8888: - return DSPF_UNKNOWN; - case SDL_PIXELFORMAT_ARGB2101010: - return DSPF_UNKNOWN; - default: - return DSPF_UNKNOWN; - } -} - -static int +static void DirectFB_ActivateRenderer(SDL_Renderer * renderer) { SDL_DFB_RENDERERDATA(renderer); @@ -317,24 +399,15 @@ SDL_DFB_WINDOWDATA(window); if (renddata->size_changed || windata->wm_needs_redraw) { -// DirectFB_AdjustWindowSurface(window); + DirectFB_AdjustWindowSurface(window); } - return 0; } -static int -DirectFB_DisplayModeChanged(SDL_Renderer * renderer) -{ - SDL_DFB_RENDERERDATA(renderer); - - renddata->size_changed = SDL_TRUE; - return 0; -} static int DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture) { - SDL_DFB_RENDERERDATA(renderer); + //SDL_DFB_RENDERERDATA(renderer); SDL_Window *window = renderer->window; SDL_VideoDisplay *display = window->display; SDL_DFB_DEVICEDATA(display->device); @@ -343,7 +416,7 @@ DFBDisplayLayerConfig layconf; DFBResult ret; - if (renddata->isyuvdirect && (dispdata->vidID >= 0) + if (devdata->use_yuv_direct && (dispdata->vidID >= 0) && (!dispdata->vidIDinuse) && SDL_ISPIXELFORMAT_FOURCC(data->format)) { layconf.flags = @@ -351,7 +424,7 @@ DLCONF_SURFACE_CAPS; layconf.width = texture->w; layconf.height = texture->h; - layconf.pixelformat = SDLToDFBPixelFormat(data->format); + layconf.pixelformat = DirectFB_SDLToDFBPixelFormat(data->format); layconf.surface_caps = DSCAPS_VIDEOONLY | DSCAPS_DOUBLE; SDL_DFB_CHECKERR(devdata->dfb->GetDisplayLayer(devdata->dfb, @@ -362,7 +435,7 @@ DLSCL_EXCLUSIVE)); if (devdata->use_yuv_underlays) { - ret = SDL_DFB_CHECK(dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1)); + ret = dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1); if (ret != DFB_OK) SDL_DFB_DEBUG("Underlay Setlevel not supported\n"); } @@ -398,11 +471,13 @@ DFBSurfaceDescription dsc; DFBSurfacePixelFormat pixelformat; - SDL_DFB_CALLOC(data, 1, sizeof(*data)); + DirectFB_ActivateRenderer(renderer); + + SDL_DFB_ALLOC_CLEAR(data, sizeof(*data)); texture->driverdata = data; /* find the right pixelformat */ - pixelformat = SDLToDFBPixelFormat(texture->format); + pixelformat = DirectFB_SDLToDFBPixelFormat(texture->format); if (pixelformat == DSPF_UNKNOWN) { SDL_SetError("Unknown pixel format %d\n", data->format); goto error; @@ -417,6 +492,12 @@ DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS; dsc.width = texture->w; dsc.height = texture->h; + if(texture->format == SDL_PIXELFORMAT_YV12 || + texture->format == SDL_PIXELFORMAT_IYUV) { + /* dfb has problems with odd sizes -make them even internally */ + dsc.width += (dsc.width % 2); + dsc.height += (dsc.height % 2); + } /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance * No DSCAPS_SYSTEMONLY either - let dfb decide * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8 @@ -436,18 +517,33 @@ /* Create the surface */ SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc, &data->surface)); + if (SDL_ISPIXELFORMAT_INDEXED(data->format) + && !SDL_ISPIXELFORMAT_FOURCC(data->format)) { +#if 1 + SDL_DFB_CHECKERR(data->surface->GetPalette(data->surface, &data->palette)); +#else + /* DFB has issues with blitting LUT8 surfaces. + * Creating a new palette does not help. + */ + DFBPaletteDescription pal_desc; + pal_desc.flags = DPDESC_SIZE; // | DPDESC_ENTRIES + pal_desc.size = 256; + SDL_DFB_CHECKERR(devdata->dfb->CreatePalette(devdata->dfb, &pal_desc,&data->palette)); + SDL_DFB_CHECKERR(data->surface->SetPalette(data->surface, data->palette)); +#endif + } + } #if (DFB_VERSION_ATLEAST(1,2,0)) data->render_options = DSRO_NONE; #endif - if (texture->access == SDL_TEXTUREACCESS_STREAMING) { /* 3 plane YUVs return 1 bpp, but we need more space for other planes */ if(texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { - SDL_DFB_CALLOC(data->pixels, 1, (texture->h * data->pitch * 3 + texture->h * data->pitch * 3 % 2) / 2); + SDL_DFB_ALLOC_CLEAR(data->pixels, (texture->h * data->pitch + ((texture->h + texture->h % 2) * (data->pitch + data->pitch % 2) * 2) / 4)); } else { - SDL_DFB_CALLOC(data->pixels, 1, texture->h * data->pitch); + SDL_DFB_ALLOC_CLEAR(data->pixels, texture->h * data->pitch); } } @@ -477,6 +573,116 @@ } static int +DirectFB_SetTexturePalette(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Color * colors, int firstcolor, + int ncolors) +{ + DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata; + if (SDL_ISPIXELFORMAT_INDEXED(data->format) + && !SDL_ISPIXELFORMAT_FOURCC(data->format)) { + DFBColor entries[256]; + int i; + + if (ncolors > 256) + ncolors = 256; + + for (i = 0; i < ncolors; ++i) { + entries[i].r = colors[i].r; + entries[i].g = colors[i].g; + entries[i].b = colors[i].b; + entries[i].a = 0xff; + } + SDL_DFB_CHECKERR(data-> + palette->SetEntries(data->palette, entries, ncolors, firstcolor)); + return 0; + } else { + SDL_SetError("YUV textures don't have a palette"); + return -1; + } + error: + return -1; +} + +static int +DirectFB_GetTexturePalette(SDL_Renderer * renderer, + SDL_Texture * texture, SDL_Color * colors, + int firstcolor, int ncolors) +{ + DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata; + + if (SDL_ISPIXELFORMAT_INDEXED(data->format) + && !SDL_ISPIXELFORMAT_FOURCC(data->format)) { + DFBColor entries[256]; + int i; + + SDL_DFB_CHECKERR(data-> + palette->GetEntries(data->palette, entries, ncolors, + firstcolor)); + + for (i = 0; i < ncolors; ++i) { + colors[i].r = entries[i].r; + colors[i].g = entries[i].g; + colors[i].b = entries[i].b; + colors->unused = SDL_ALPHA_OPAQUE; + } + return 0; + } else { + SDL_SetError("YUV textures don't have a palette"); + return -1; + } + error: + return -1; +} + +static int +DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + return 0; +} + +static int +DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + return 0; +} + +static int +DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) +{ + switch (texture->blendMode) { + case SDL_BLENDMODE_NONE: + //case SDL_BLENDMODE_MASK: + case SDL_BLENDMODE_BLEND: + case SDL_BLENDMODE_ADD: + case SDL_BLENDMODE_MOD: + return 0; + default: + SDL_Unsupported(); + texture->blendMode = SDL_BLENDMODE_NONE; + return -1; + } +} + +static int +DirectFB_SetDrawBlendMode(SDL_Renderer * renderer) +{ + switch (renderer->blendMode) { + case SDL_BLENDMODE_NONE: + //case SDL_BLENDMODE_MASK: + case SDL_BLENDMODE_BLEND: + case SDL_BLENDMODE_ADD: + case SDL_BLENDMODE_MOD: + return 0; + default: + SDL_Unsupported(); + renderer->blendMode = SDL_BLENDMODE_NONE; + return -1; + } +} + +#if 0 +static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture) { #if (DFB_VERSION_ATLEAST(1,2,0)) @@ -504,6 +710,7 @@ #endif return 0; } +#endif static int DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, @@ -515,9 +722,16 @@ Uint8 *src, *dst; int row; size_t length; - int bpp = DFB_BYTES_PER_PIXEL(SDLToDFBPixelFormat(texture->format)); + int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format)); // FIXME: SDL_BYTESPERPIXEL(texture->format) broken for yuv yv12 3 planes + DirectFB_ActivateRenderer(renderer); + + if ((texture->format == SDL_PIXELFORMAT_YV12) || + (texture->format == SDL_PIXELFORMAT_IYUV)) { + bpp = 1; + } + SDL_DFB_CHECKERR(data->surface->Lock(data->surface, DSLF_WRITE | DSLF_READ, ((void **) &dpixels), &dpitch)); @@ -530,24 +744,25 @@ dst += dpitch; } /* copy other planes for 3 plane formats */ - if (texture->format == SDL_PIXELFORMAT_YV12 || - texture->format == SDL_PIXELFORMAT_IYUV) { + if ((texture->format == SDL_PIXELFORMAT_YV12) || + (texture->format == SDL_PIXELFORMAT_IYUV)) { src = (Uint8 *) pixels + texture->h * pitch; dst = (Uint8 *) dpixels + texture->h * dpitch + rect->y * dpitch / 4 + rect->x * bpp / 2; - for (row = 0; row < rect->h / 2; ++row) { + for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) { SDL_memcpy(dst, src, length / 2); src += pitch / 2; dst += dpitch / 2; } src = (Uint8 *) pixels + texture->h * pitch + texture->h * pitch / 4; dst = (Uint8 *) dpixels + texture->h * dpitch + texture->h * dpitch / 4 + rect->y * dpitch / 4 + rect->x * bpp / 2; - for (row = 0; row < rect->h / 2; ++row) { + for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) { SDL_memcpy(dst, src, length / 2); src += pitch / 2; dst += dpitch / 2; } } SDL_DFB_CHECKERR(data->surface->Unlock(data->surface)); + data->isDirty = 0; return 0; error: return 1; @@ -556,15 +771,18 @@ static int DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, - const SDL_Rect * rect, int markDirty, - void **pixels, int *pitch) + const SDL_Rect * rect, void **pixels, int *pitch) { DirectFB_TextureData *texturedata = (DirectFB_TextureData *) texture->driverdata; + DirectFB_ActivateRenderer(renderer); + +#if 0 if (markDirty) { SDL_AddDirtyRect(&texturedata->dirty, rect); } +#endif if (texturedata->display) { void *fdata; @@ -579,8 +797,9 @@ *pixels = (void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch + - rect->x * DFB_BYTES_PER_PIXEL(SDLToDFBPixelFormat(texture->format))); + rect->x * DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format))); *pitch = texturedata->pitch; + texturedata->isDirty = 1; } return 0; @@ -594,12 +813,15 @@ DirectFB_TextureData *texturedata = (DirectFB_TextureData *) texture->driverdata; + DirectFB_ActivateRenderer(renderer); + if (texturedata->display) { SDL_DFB_CHECK(texturedata->surface->Unlock(texturedata->surface)); texturedata->pixels = NULL; } } +#if 0 static void DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects, const SDL_Rect * rects) @@ -611,6 +833,7 @@ SDL_AddDirtyRect(&data->dirty, &rects[i]); } } +#endif static int PrepareDraw(SDL_Renderer * renderer) @@ -630,9 +853,11 @@ switch (renderer->blendMode) { case SDL_BLENDMODE_NONE: + //case SDL_BLENDMODE_MASK: case SDL_BLENDMODE_BLEND: break; case SDL_BLENDMODE_ADD: + case SDL_BLENDMODE_MOD: r = ((int) r * (int) a) / 255; g = ((int) g * (int) a) / 255; b = ((int) b * (int) a) / 255; @@ -653,6 +878,8 @@ SDL_DFB_WINDOWSURFACE(data->window); int i; + DirectFB_ActivateRenderer(renderer); + PrepareDraw(renderer); for (i=0; i < count; i++) SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, points[i].x, points[i].y, points[i].x, points[i].y)); @@ -668,6 +895,8 @@ SDL_DFB_WINDOWSURFACE(data->window); int i; + DirectFB_ActivateRenderer(renderer); + PrepareDraw(renderer); /* Use antialiasing when available */ #if (DFB_VERSION_ATLEAST(1,2,0)) @@ -683,12 +912,34 @@ } static int +DirectFB_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) +{ + DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata; + SDL_DFB_WINDOWSURFACE(data->window); + int i; + + DirectFB_ActivateRenderer(renderer); + + PrepareDraw(renderer); + + for (i=0; i<count; i++) + SDL_DFB_CHECKERR(destsurf->DrawRectangle(destsurf, rects[i]->x, rects[i]->y, + rects[i]->w, rects[i]->h)); + + return 0; + error: + return -1; +} + +static int DirectFB_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count) { DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata; SDL_DFB_WINDOWSURFACE(data->window); int i; + DirectFB_ActivateRenderer(renderer); + PrepareDraw(renderer); for (i=0; i<count; i++) @@ -708,7 +959,9 @@ SDL_DFB_WINDOWSURFACE(data->window); DirectFB_TextureData *texturedata = (DirectFB_TextureData *) texture->driverdata; - Uint8 alpha = 0xFF; + Uint8 alpha, r, g, b; + + DirectFB_ActivateRenderer(renderer); if (texturedata->display) { int px, py; @@ -722,7 +975,7 @@ srcrect->x, srcrect->y, srcrect->w, srcrect->h)); - SDL_DFB_CHECK(windata->window->GetPosition(windata->window, &px, &py)); + SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin, &px, &py)); px += windata->client.x; py += windata->client.y; SDL_DFB_CHECKERR(dispdata-> @@ -735,10 +988,11 @@ DFBRectangle sr, dr; DFBSurfaceBlittingFlags flags = 0; +#if 0 if (texturedata->dirty.list) { SDL_DirtyRect *dirty; void *pixels; - int bpp = DFB_BYTES_PER_PIXEL(SDLToDFBPixelFormat(texture->format)); + int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format)); int pitch = texturedata->pitch; for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) { @@ -747,38 +1001,43 @@ (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch + rect->x * bpp); DirectFB_UpdateTexture(renderer, texture, rect, - texturedata->pixels, + pixels, texturedata->pitch); } SDL_ClearDirtyRects(&texturedata->dirty); } +#endif + if (texturedata->isDirty) + { + SDL_Rect rect; + + rect.x = 0; + rect.y = 0; + rect.w = texture->w; + rect.h = texture->h; + + DirectFB_UpdateTexture(renderer, texture, &rect, texturedata->pixels, texturedata->pitch); + } SDLtoDFBRect(srcrect, &sr); SDLtoDFBRect(dstrect, &dr); - SDL_DFB_CHECKERR(destsurf-> - SetColor(destsurf, 0xFF, 0xFF, 0xFF, 0xFF)); - if (texture-> - modMode & (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA)) - { - if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) { - alpha = texture->a; - SDL_DFB_CHECKERR(destsurf->SetColor(destsurf, 0xFF, 0xFF, - 0xFF, alpha)); - } - if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { + alpha = r = g = b = 0xff; + if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA){ + alpha = texture->a; + flags |= DSBLIT_BLEND_COLORALPHA; + } - SDL_DFB_CHECKERR(destsurf->SetColor(destsurf, - texture->r, - texture->g, - texture->b, alpha)); - flags |= DSBLIT_COLORIZE; - } - if (alpha < 0xFF) - flags |= DSBLIT_SRC_PREMULTCOLOR; - } else - SDL_DFB_CHECKERR(destsurf->SetColor(destsurf, 0xFF, 0xFF, - 0xFF, 0xFF)); + if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { + r = texture->r; + g = texture->g; + b = texture->b; + flags |= DSBLIT_COLORIZE; + } + SDL_DFB_CHECKERR(destsurf-> + SetColor(destsurf, r, g, b, alpha)); + + // ???? flags |= DSBLIT_SRC_PREMULTCOLOR; SetBlendMode(data, texture->blendMode, texturedata); @@ -812,13 +1071,27 @@ DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; SDL_DFB_WINDOWDATA(window); + SDL_ShapeData *shape_data = (window->shaper ? window->shaper->driverdata : NULL); - DFBRectangle sr; + DirectFB_ActivateRenderer(renderer); - sr.x = 0; - sr.y = 0; - sr.w = window->w; - sr.h = window->h; + if (shape_data && shape_data->surface) { + /* saturate the window surface alpha channel */ + SDL_DFB_CHECK(windata->window_surface->SetSrcBlendFunction(windata->window_surface, DSBF_ONE)); + SDL_DFB_CHECK(windata->window_surface->SetDstBlendFunction(windata->window_surface, DSBF_ONE)); + SDL_DFB_CHECK(windata->window_surface->SetDrawingFlags(windata->window_surface, DSDRAW_BLEND)); + SDL_DFB_CHECK(windata->window_surface->SetColor(windata->window_surface, 0, 0, 0, 0xff)); + SDL_DFB_CHECK(windata->window_surface->FillRectangle(windata->window_surface, 0,0, windata->size.w, windata->size.h)); + + /* blit the mask */ + SDL_DFB_CHECK(windata->surface->SetSrcBlendFunction(windata->surface, DSBF_DESTCOLOR)); + SDL_DFB_CHECK(windata->surface->SetDstBlendFunction(windata->surface, DSBF_ZERO)); + SDL_DFB_CHECK(windata->surface->SetBlittingFlags(windata->surface, DSBLIT_BLEND_ALPHACHANNEL)); +#if (DFB_VERSION_ATLEAST(1,2,0)) + SDL_DFB_CHECK(windata->surface->SetRenderOptions(windata->surface, DSRO_NONE)); +#endif + SDL_DFB_CHECK(windata->surface->Blit(windata->surface, shape_data->surface, NULL, 0, 0)); + } /* Send the data to the display */ SDL_DFB_CHECK(windata->window_surface->Flip(windata->window_surface, NULL, @@ -830,9 +1103,12 @@ { DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata; + DirectFB_ActivateRenderer(renderer); + if (!data) { return; } + //SDL_FreeDirtyRects(&data->dirty); SDL_DFB_RELEASE(data->palette); SDL_DFB_RELEASE(data->surface); if (data->display) { @@ -844,7 +1120,6 @@ DLSCL_ADMINISTRATIVE)); SDL_DFB_RELEASE(dispdata->vidlayer); } - SDL_FreeDirtyRects(&data->dirty); SDL_DFB_FREE(data->pixels); SDL_free(data); texture->driverdata = NULL; @@ -854,6 +1129,13 @@ DirectFB_DestroyRenderer(SDL_Renderer * renderer) { DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata; + SDL_VideoDisplay *display = renderer->window->display; + +#if 0 + if (display->palette) { + SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, data); + } +#endif if (data) { SDL_free(data); @@ -861,4 +1143,58 @@ SDL_free(renderer); } +static int +DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, void * pixels, int pitch) +{ + SDL_Window *window = renderer->window; + SDL_DFB_WINDOWDATA(window); + Uint32 sdl_format; + void * laypixels; + int laypitch; + DFBSurfacePixelFormat dfb_format; + + DirectFB_ActivateRenderer(renderer); + + SDL_DFB_CHECK(windata->surface->GetPixelFormat(windata->surface, &dfb_format)); + sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format); + SDL_DFB_CHECK(windata->surface->Lock(windata->surface, DSLF_READ, (void **) &laypixels, &laypitch)); + + laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) ); + SDL_ConvertPixels(rect->w, rect->h, + sdl_format, laypixels, laypitch, + format, pixels, pitch); + + SDL_DFB_CHECK(windata->surface->Unlock(windata->surface)); + + return 0; +} + +static int +DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, const void * pixels, int pitch) +{ + SDL_Window *window = renderer->window; + SDL_DFB_WINDOWDATA(window); + Uint32 sdl_format; + void * laypixels; + int laypitch; + DFBSurfacePixelFormat dfb_format; + + SDL_DFB_CHECK(windata->surface->GetPixelFormat(windata->surface, &dfb_format)); + sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format); + + SDL_DFB_CHECK(windata->surface->Lock(windata->surface, DSLF_WRITE, (void **) &laypixels, &laypitch)); + + laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) ); + SDL_ConvertPixels(rect->w, rect->h, + format, pixels, pitch, + sdl_format, laypixels, laypitch); + + SDL_DFB_CHECK(windata->surface->Unlock(windata->surface)); + + return 0; +} + + /* vi: set ts=4 sw=4 expandtab: */