src/video/directfb/SDL_DirectFB_render.c
author Gabriel Jacobo <gabomdq@gmail.com>
Wed, 21 Aug 2013 09:47:10 -0300
changeset 7678 286c42d7c5ed
parent 7677 871d43c6968a
child 7719 31b5f9ff36ca
permissions -rw-r--r--
OCD fixes: Adds a space after /* (glory to regular expressions!)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_DIRECTFB
    24 #include "SDL_DirectFB_window.h"
    25 #include "SDL_DirectFB_modes.h"
    26 
    27 #include "SDL_syswm.h"
    28 #include "SDL_DirectFB_shape.h"
    29 
    30 #include "../SDL_sysvideo.h"
    31 #include "../../render/SDL_sysrender.h"
    32 
    33 #ifndef DFB_VERSION_ATLEAST
    34 
    35 #define DFB_VERSIONNUM(X, Y, Z)                     \
    36     ((X)*1000 + (Y)*100 + (Z))
    37 
    38 #define DFB_COMPILEDVERSION \
    39     DFB_VERSIONNUM(DIRECTFB_MAJOR_VERSION, DIRECTFB_MINOR_VERSION, DIRECTFB_MICRO_VERSION)
    40 
    41 #define DFB_VERSION_ATLEAST(X, Y, Z) \
    42     (DFB_COMPILEDVERSION >= DFB_VERSIONNUM(X, Y, Z))
    43 
    44 #define SDL_DFB_CHECK(x)    x
    45 
    46 #endif
    47 
    48 /* the following is not yet tested ... */
    49 #define USE_DISPLAY_PALETTE         (0)
    50 
    51 
    52 #define SDL_DFB_RENDERERDATA(rend) DirectFB_RenderData *renddata = ((rend) ? (DirectFB_RenderData *) (rend)->driverdata : NULL)
    53 
    54 
    55 /* GDI renderer implementation */
    56 
    57 static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window,
    58                                              Uint32 flags);
    59 static void DirectFB_ActivateRenderer(SDL_Renderer * renderer);
    60 static int DirectFB_CreateTexture(SDL_Renderer * renderer,
    61                                   SDL_Texture * texture);
    62 static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
    63                                        SDL_Texture * texture,
    64                                        void **pixels, int *pitch);
    65 static int DirectFB_SetTexturePalette(SDL_Renderer * renderer,
    66                                       SDL_Texture * texture,
    67                                       const SDL_Color * colors,
    68                                       int firstcolor, int ncolors);
    69 static int DirectFB_GetTexturePalette(SDL_Renderer * renderer,
    70                                       SDL_Texture * texture,
    71                                       SDL_Color * colors,
    72                                       int firstcolor, int ncolors);
    73 static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,
    74                                        SDL_Texture * texture);
    75 static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer,
    76                                        SDL_Texture * texture);
    77 static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,
    78                                         SDL_Texture * texture);
    79 static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer,
    80                                         SDL_Texture * texture);
    81 static int DirectFB_UpdateTexture(SDL_Renderer * renderer,
    82                                   SDL_Texture * texture,
    83                                   const SDL_Rect * rect,
    84                                   const void *pixels, int pitch);
    85 static int DirectFB_LockTexture(SDL_Renderer * renderer,
    86                                 SDL_Texture * texture,
    87                                 const SDL_Rect * rect,
    88                                 void **pixels, int *pitch);
    89 static void DirectFB_UnlockTexture(SDL_Renderer * renderer,
    90                                    SDL_Texture * texture);
    91 static void DirectFB_DirtyTexture(SDL_Renderer * renderer,
    92                                   SDL_Texture * texture, int numrects,
    93                                   const SDL_Rect * rects);
    94 static int DirectFB_SetDrawBlendMode(SDL_Renderer * renderer);
    95 static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer,
    96                                 const SDL_FPoint * points, int count);
    97 static int DirectFB_RenderDrawLines(SDL_Renderer * renderer,
    98                                const SDL_FPoint * points, int count);
    99 static int DirectFB_RenderDrawRects(SDL_Renderer * renderer,
   100         const SDL_Rect ** rects, int count);
   101 static int DirectFB_RenderFillRects(SDL_Renderer * renderer,
   102         const SDL_FRect * rects, int count);
   103 static int DirectFB_RenderCopy(SDL_Renderer * renderer,
   104                                SDL_Texture * texture,
   105                                const SDL_Rect * srcrect,
   106                                const SDL_FRect * dstrect);
   107 static void DirectFB_RenderPresent(SDL_Renderer * renderer);
   108 static void DirectFB_DestroyTexture(SDL_Renderer * renderer,
   109                                     SDL_Texture * texture);
   110 static void DirectFB_DestroyRenderer(SDL_Renderer * renderer);
   111 static int DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   112                      Uint32 format, void * pixels, int pitch);
   113 static int DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   114                       Uint32 format, const void * pixels, int pitch);
   115 static int DirectFB_UpdateViewport(SDL_Renderer * renderer);
   116 static int DirectFB_UpdateClipRect(SDL_Renderer * renderer);
   117 static int DirectFB_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
   118 
   119 static int PrepareDraw(SDL_Renderer * renderer);
   120 
   121 
   122 #define SDL_DFB_WINDOWSURFACE(win)  IDirectFBSurface *destsurf = ((DFB_WindowData *) ((win)->driverdata))->surface;
   123 
   124 SDL_RenderDriver DirectFB_RenderDriver = {
   125     DirectFB_CreateRenderer,
   126     {
   127      "directfb",
   128      (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
   129      /* (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
   130       SDL_TEXTUREMODULATE_ALPHA),
   131       (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND |
   132       SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
   133      (SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST |
   134       SDL_SCALEMODE_SLOW | SDL_SCALEMODE_BEST), */
   135      0,
   136      {
   137              /* formats filled in later */
   138      },
   139      0,
   140      0}
   141 };
   142 
   143 typedef struct
   144 {
   145     SDL_Window *window;
   146     DFBSurfaceFlipFlags flipflags;
   147     int size_changed;
   148     int lastBlendMode;
   149     DFBSurfaceBlittingFlags blitFlags;
   150     DFBSurfaceDrawingFlags drawFlags;
   151     IDirectFBSurface* target;
   152 } DirectFB_RenderData;
   153 
   154 typedef struct
   155 {
   156     IDirectFBSurface *surface;
   157     Uint32 format;
   158     void *pixels;
   159     int pitch;
   160     IDirectFBPalette *palette;
   161     int isDirty;
   162 
   163     SDL_VideoDisplay *display;      /* only for yuv textures */
   164 
   165 #if (DFB_VERSION_ATLEAST(1,2,0))
   166     DFBSurfaceRenderOptions render_options;
   167 #endif
   168 } DirectFB_TextureData;
   169 
   170 static __inline__ void
   171 SDLtoDFBRect(const SDL_Rect * sr, DFBRectangle * dr)
   172 {
   173     dr->x = sr->x;
   174     dr->y = sr->y;
   175     dr->h = sr->h;
   176     dr->w = sr->w;
   177 }
   178 static __inline__ void
   179 SDLtoDFBRect_Float(const SDL_FRect * sr, DFBRectangle * dr)
   180 {
   181     dr->x = sr->x;
   182     dr->y = sr->y;
   183     dr->h = sr->h;
   184     dr->w = sr->w;
   185 }
   186 
   187 
   188 static int
   189 TextureHasAlpha(DirectFB_TextureData * data)
   190 {
   191     /* Drawing primitive ? */
   192     if (!data)
   193         return 0;
   194 
   195     return (DFB_PIXELFORMAT_HAS_ALPHA(DirectFB_SDLToDFBPixelFormat(data->format)) ? 1 : 0);
   196 #if 0
   197     switch (data->format) {
   198     case SDL_PIXELFORMAT_INDEX4LSB:
   199     case SDL_PIXELFORMAT_INDEX4MSB:
   200     case SDL_PIXELFORMAT_ARGB4444:
   201     case SDL_PIXELFORMAT_ARGB1555:
   202     case SDL_PIXELFORMAT_ARGB8888:
   203     case SDL_PIXELFORMAT_RGBA8888:
   204     case SDL_PIXELFORMAT_ABGR8888:
   205     case SDL_PIXELFORMAT_BGRA8888:
   206     case SDL_PIXELFORMAT_ARGB2101010:
   207        return 1;
   208     default:
   209         return 0;
   210     }
   211 #endif
   212 }
   213 
   214 static inline IDirectFBSurface *get_dfb_surface(SDL_Window *window)
   215 {
   216     SDL_SysWMinfo wm_info;
   217     SDL_memset(&wm_info, 0, sizeof(SDL_SysWMinfo));
   218 
   219     SDL_VERSION(&wm_info.version);
   220     SDL_GetWindowWMInfo(window, &wm_info);
   221 
   222     return wm_info.info.dfb.surface;
   223 }
   224 
   225 static inline IDirectFBWindow *get_dfb_window(SDL_Window *window)
   226 {
   227     SDL_SysWMinfo wm_info;
   228     SDL_memset(&wm_info, 0, sizeof(SDL_SysWMinfo));
   229 
   230     SDL_VERSION(&wm_info.version);
   231     SDL_GetWindowWMInfo(window, &wm_info);
   232 
   233     return wm_info.info.dfb.window;
   234 }
   235 
   236 static void
   237 SetBlendMode(DirectFB_RenderData * data, int blendMode,
   238              DirectFB_TextureData * source)
   239 {
   240     IDirectFBSurface *destsurf = data->target;
   241 
   242     /* FIXME: check for format change */
   243     if (1 || data->lastBlendMode != blendMode) {
   244         switch (blendMode) {
   245         case SDL_BLENDMODE_NONE:
   246                                            /**< No blending */
   247             data->blitFlags = DSBLIT_NOFX;
   248             data->drawFlags = DSDRAW_NOFX;
   249             SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE));
   250             SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ZERO));
   251             break;
   252 #if 0
   253         case SDL_BLENDMODE_MASK:
   254             data->blitFlags =  DSBLIT_BLEND_ALPHACHANNEL;
   255             data->drawFlags = DSDRAW_BLEND;
   256             SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
   257             SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
   258             break;
   259 #endif
   260         case SDL_BLENDMODE_BLEND:
   261             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   262             data->drawFlags = DSDRAW_BLEND;
   263             SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
   264             SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
   265             break;
   266         case SDL_BLENDMODE_ADD:
   267             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   268             data->drawFlags = DSDRAW_BLEND;
   269             /* FIXME: SRCALPHA kills performance on radeon ... */
   270              * It will be cheaper to copy the surface to a temporary surface and premultiply
   271              */
   272             if (source && TextureHasAlpha(source))
   273                 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_SRCALPHA));
   274             else
   275                 SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ONE));
   276             SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_ONE));
   277             break;
   278         case SDL_BLENDMODE_MOD:
   279             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   280             data->drawFlags = DSDRAW_BLEND;
   281             SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_ZERO));
   282             SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_SRCCOLOR));
   283 
   284             break;
   285         }
   286         data->lastBlendMode = blendMode;
   287     }
   288 }
   289 
   290 static int
   291 DisplayPaletteChanged(void *userdata, SDL_Palette * palette)
   292 {
   293 #if USE_DISPLAY_PALETTE
   294     DirectFB_RenderData *data = (DirectFB_RenderData *) userdata;
   295     SDL_DFB_WINDOWSURFACE(data->window);
   296     IDirectFBPalette *surfpal;
   297 
   298     int i;
   299     int ncolors;
   300     DFBColor entries[256];
   301 
   302     SDL_DFB_CHECKERR(destsurf->GetPalette(destsurf, &surfpal));
   303 
   304     /* FIXME: number of colors */
   305     ncolors = (palette->ncolors < 256 ? palette->ncolors : 256);
   306 
   307     for (i = 0; i < ncolors; ++i) {
   308         entries[i].r = palette->colors[i].r;
   309         entries[i].g = palette->colors[i].g;
   310         entries[i].b = palette->colors[i].b;
   311         entries[i].a = palette->colors[i].unused;
   312     }
   313     SDL_DFB_CHECKERR(surfpal->SetEntries(surfpal, entries, ncolors, 0));
   314     return 0;
   315   error:
   316 #else
   317     SDL_Unsupported();
   318 #endif
   319     return -1;
   320 }
   321 
   322 static void
   323 DirectFB_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   324 {
   325     SDL_DFB_RENDERERDATA(renderer);
   326 
   327     if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
   328         /* Rebind the context to the window area and update matrices */
   329         /* SDL_CurrentContext = NULL; */
   330         /* data->updateSize = SDL_TRUE; */
   331         renddata->size_changed = SDL_TRUE;
   332    }
   333 }
   334 
   335 int
   336 DirectFB_RenderClear(SDL_Renderer * renderer)
   337 {
   338     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   339     IDirectFBSurface *destsurf = data->target;
   340 
   341     DirectFB_ActivateRenderer(renderer);
   342 
   343     PrepareDraw(renderer);
   344 
   345     destsurf->Clear(destsurf, renderer->r, renderer->g, renderer->b, renderer->a);
   346 
   347 
   348     return 0;
   349 }
   350 
   351 SDL_Renderer *
   352 DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
   353 {
   354     IDirectFBSurface *winsurf = get_dfb_surface(window);
   355     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   356     SDL_Renderer *renderer = NULL;
   357     DirectFB_RenderData *data = NULL;
   358     DFBSurfaceCapabilities scaps;
   359 
   360     SDL_DFB_ALLOC_CLEAR(renderer, sizeof(*renderer));
   361     SDL_DFB_ALLOC_CLEAR(data, sizeof(*data));
   362 
   363     renderer->WindowEvent = DirectFB_WindowEvent;
   364     renderer->CreateTexture = DirectFB_CreateTexture;
   365     renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod;
   366     renderer->SetTextureColorMod = DirectFB_SetTextureColorMod;
   367     renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode;
   368     renderer->UpdateTexture = DirectFB_UpdateTexture;
   369     renderer->LockTexture = DirectFB_LockTexture;
   370     renderer->RenderClear = DirectFB_RenderClear;
   371     renderer->UnlockTexture = DirectFB_UnlockTexture;
   372     renderer->RenderDrawPoints = DirectFB_RenderDrawPoints;
   373     renderer->RenderDrawLines = DirectFB_RenderDrawLines;
   374     /* SetDrawColor - no needed */
   375     renderer->RenderFillRects = DirectFB_RenderFillRects;
   376 
   377     renderer->RenderCopy = DirectFB_RenderCopy;
   378     renderer->RenderPresent = DirectFB_RenderPresent;
   379 
   380     /* FIXME: Yet to be tested */
   381     renderer->RenderReadPixels = DirectFB_RenderReadPixels;
   382     /* renderer->RenderWritePixels = DirectFB_RenderWritePixels; */
   383 
   384     renderer->DestroyTexture = DirectFB_DestroyTexture;
   385     renderer->DestroyRenderer = DirectFB_DestroyRenderer;
   386     renderer->UpdateViewport = DirectFB_UpdateViewport;
   387     renderer->UpdateClipRect = DirectFB_UpdateClipRect;
   388     renderer->SetRenderTarget = DirectFB_SetRenderTarget;
   389 
   390 #if 0
   391     renderer->QueryTexturePixels = DirectFB_QueryTexturePixels;
   392     renderer->SetTexturePalette = DirectFB_SetTexturePalette;
   393     renderer->GetTexturePalette = DirectFB_GetTexturePalette;
   394     renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
   395     renderer->DirtyTexture = DirectFB_DirtyTexture;
   396     renderer->SetDrawBlendMode = DirectFB_SetDrawBlendMode;
   397     renderer->RenderDrawRects = DirectFB_RenderDrawRects;
   398 #endif
   399 
   400     renderer->info = DirectFB_RenderDriver.info;
   401     renderer->window = window;      /* SDL window */
   402     renderer->driverdata = data;
   403 
   404     renderer->info.flags =
   405         SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
   406 
   407     data->window = window;
   408     data->target = winsurf;
   409 
   410     data->flipflags = DSFLIP_PIPELINE | DSFLIP_BLIT;
   411 
   412     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   413         data->flipflags |= DSFLIP_WAITFORSYNC | DSFLIP_ONSYNC;
   414         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   415     } else
   416         data->flipflags |= DSFLIP_ONSYNC;
   417 
   418     SDL_DFB_CHECKERR(winsurf->GetCapabilities(winsurf, &scaps));
   419 
   420 #if 0
   421     if (scaps & DSCAPS_DOUBLE)
   422         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
   423     else if (scaps & DSCAPS_TRIPLE)
   424         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
   425     else
   426         renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
   427 #endif
   428 
   429     DirectFB_SetSupportedPixelFormats(&renderer->info);
   430 
   431 #if 0
   432     /* Set up a palette watch on the display palette */
   433     if (display-> palette) {
   434         SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data);
   435     }
   436 #endif
   437 
   438     return renderer;
   439 
   440   error:
   441     SDL_DFB_FREE(renderer);
   442     SDL_DFB_FREE(data);
   443     return NULL;
   444 }
   445 
   446 static void
   447 DirectFB_ActivateRenderer(SDL_Renderer * renderer)
   448 {
   449     SDL_DFB_RENDERERDATA(renderer);
   450     SDL_Window *window = renderer->window;
   451     SDL_DFB_WINDOWDATA(window);
   452 
   453     if (renddata->size_changed /* || windata->wm_needs_redraw */) {
   454         renddata->size_changed = SDL_FALSE;
   455     }
   456 }
   457 
   458 
   459 static int
   460 DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
   461 {
   462     SDL_Window *window = renderer->window;
   463     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   464     SDL_DFB_DEVICEDATA(display->device);
   465     DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   466     DirectFB_TextureData *data = texture->driverdata;
   467     DFBDisplayLayerConfig layconf;
   468     DFBResult ret;
   469 
   470     if (devdata->use_yuv_direct && (dispdata->vidID >= 0)
   471         && (!dispdata->vidIDinuse)
   472         && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   473         layconf.flags =
   474             DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
   475             DLCONF_SURFACE_CAPS;
   476         layconf.width = texture->w;
   477         layconf.height = texture->h;
   478         layconf.pixelformat = DirectFB_SDLToDFBPixelFormat(data->format);
   479         layconf.surface_caps = DSCAPS_VIDEOONLY | DSCAPS_DOUBLE;
   480 
   481         SDL_DFB_CHECKERR(devdata->dfb->GetDisplayLayer(devdata->dfb,
   482                                                        dispdata->vidID,
   483                                                        &dispdata->vidlayer));
   484         SDL_DFB_CHECKERR(dispdata->
   485                          vidlayer->SetCooperativeLevel(dispdata->vidlayer,
   486                                                        DLSCL_EXCLUSIVE));
   487 
   488         if (devdata->use_yuv_underlays) {
   489             ret = dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1);
   490             if (ret != DFB_OK)
   491                 SDL_DFB_DEBUG("Underlay Setlevel not supported\n");
   492         }
   493         SDL_DFB_CHECKERR(dispdata->
   494                          vidlayer->SetConfiguration(dispdata->vidlayer,
   495                                                     &layconf));
   496         SDL_DFB_CHECKERR(dispdata->
   497                          vidlayer->GetSurface(dispdata->vidlayer,
   498                                               &data->surface));
   499         dispdata->vidIDinuse = 1;
   500         data->display = display;
   501         return 0;
   502     }
   503     return 1;
   504   error:
   505     if (dispdata->vidlayer) {
   506         SDL_DFB_RELEASE(data->surface);
   507         SDL_DFB_CHECKERR(dispdata->
   508                          vidlayer->SetCooperativeLevel(dispdata->vidlayer,
   509                                                        DLSCL_ADMINISTRATIVE));
   510         SDL_DFB_RELEASE(dispdata->vidlayer);
   511     }
   512     return 1;
   513 }
   514 
   515 static int
   516 DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   517 {
   518     SDL_Window *window = renderer->window;
   519     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   520     SDL_DFB_DEVICEDATA(display->device);
   521     DirectFB_TextureData *data;
   522     DFBSurfaceDescription dsc;
   523     DFBSurfacePixelFormat pixelformat;
   524 
   525     DirectFB_ActivateRenderer(renderer);
   526 
   527     SDL_DFB_ALLOC_CLEAR(data, sizeof(*data));
   528     texture->driverdata = data;
   529 
   530     /* find the right pixelformat */
   531     pixelformat = DirectFB_SDLToDFBPixelFormat(texture->format);
   532     if (pixelformat == DSPF_UNKNOWN) {
   533         SDL_SetError("Unknown pixel format %d\n", data->format);
   534         goto error;
   535     }
   536 
   537     data->format = texture->format;
   538     data->pitch = texture->w * DFB_BYTES_PER_PIXEL(pixelformat);
   539 
   540     if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
   541         /* fill surface description */
   542         dsc.flags =
   543             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   544         dsc.width = texture->w;
   545         dsc.height = texture->h;
   546         if(texture->format == SDL_PIXELFORMAT_YV12 ||
   547            texture->format == SDL_PIXELFORMAT_IYUV) {
   548            /* dfb has problems with odd sizes -make them even internally */
   549            dsc.width += (dsc.width % 2);
   550            dsc.height += (dsc.height % 2);
   551         }
   552         /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
   553          * No DSCAPS_SYSTEMONLY either - let dfb decide
   554          * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
   555          * Depends on other settings as well. Let dfb decide.
   556          */
   557         dsc.caps = DSCAPS_PREMULTIPLIED;
   558 #if 0
   559         if (texture->access == SDL_TEXTUREACCESS_STREAMING)
   560             dsc.caps |= DSCAPS_SYSTEMONLY;
   561         else
   562             dsc.caps |= DSCAPS_VIDEOONLY;
   563 #endif
   564 
   565         dsc.pixelformat = pixelformat;
   566         data->pixels = NULL;
   567 
   568         /* Create the surface */
   569         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   570                                                      &data->surface));
   571         if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   572             && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   573 #if 1
   574             SDL_DFB_CHECKERR(data->surface->GetPalette(data->surface, &data->palette));
   575 #else
   576             /* DFB has issues with blitting LUT8 surfaces.
   577              * Creating a new palette does not help.
   578              */
   579             DFBPaletteDescription pal_desc;
   580             pal_desc.flags = DPDESC_SIZE; /* | DPDESC_ENTRIES */
   581             pal_desc.size = 256;
   582             SDL_DFB_CHECKERR(devdata->dfb->CreatePalette(devdata->dfb, &pal_desc,&data->palette));
   583             SDL_DFB_CHECKERR(data->surface->SetPalette(data->surface, data->palette));
   584 #endif
   585         }
   586 
   587     }
   588 #if (DFB_VERSION_ATLEAST(1,2,0))
   589     data->render_options = DSRO_NONE;
   590 #endif
   591     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   592         /* 3 plane YUVs return 1 bpp, but we need more space for other planes */
   593         if(texture->format == SDL_PIXELFORMAT_YV12 ||
   594            texture->format == SDL_PIXELFORMAT_IYUV) {
   595             SDL_DFB_ALLOC_CLEAR(data->pixels, (texture->h * data->pitch  + ((texture->h + texture->h % 2) * (data->pitch + data->pitch % 2) * 2) / 4));
   596         } else {
   597             SDL_DFB_ALLOC_CLEAR(data->pixels, texture->h * data->pitch);
   598         }
   599     }
   600 
   601     return 0;
   602 
   603   error:
   604     SDL_DFB_RELEASE(data->palette);
   605     SDL_DFB_RELEASE(data->surface);
   606     SDL_DFB_FREE(texture->driverdata);
   607     return -1;
   608 }
   609 
   610 static int
   611 DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
   612                             SDL_Texture * texture, void **pixels, int *pitch)
   613 {
   614     DirectFB_TextureData *texturedata =
   615         (DirectFB_TextureData *) texture->driverdata;
   616 
   617     if (texturedata->display) {
   618         return -1;
   619     } else {
   620         *pixels = texturedata->pixels;
   621         *pitch = texturedata->pitch;
   622     }
   623     return 0;
   624 }
   625 
   626 static int
   627 DirectFB_SetTexturePalette(SDL_Renderer * renderer,
   628                            SDL_Texture * texture,
   629                            const SDL_Color * colors, int firstcolor,
   630                            int ncolors)
   631 {
   632     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   633     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   634         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   635         DFBColor entries[256];
   636         int i;
   637 
   638         if (ncolors > 256)
   639             ncolors = 256;
   640 
   641         for (i = 0; i < ncolors; ++i) {
   642             entries[i].r = colors[i].r;
   643             entries[i].g = colors[i].g;
   644             entries[i].b = colors[i].b;
   645             entries[i].a = 0xff;
   646         }
   647         SDL_DFB_CHECKERR(data->
   648                          palette->SetEntries(data->palette, entries, ncolors, firstcolor));
   649         return 0;
   650     } else {
   651         return SDL_SetError("YUV textures don't have a palette");
   652     }
   653   error:
   654     return -1;
   655 }
   656 
   657 static int
   658 DirectFB_GetTexturePalette(SDL_Renderer * renderer,
   659                            SDL_Texture * texture, SDL_Color * colors,
   660                            int firstcolor, int ncolors)
   661 {
   662     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   663 
   664     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   665         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   666         DFBColor entries[256];
   667         int i;
   668 
   669         SDL_DFB_CHECKERR(data->
   670                          palette->GetEntries(data->palette, entries, ncolors,
   671                                              firstcolor));
   672 
   673         for (i = 0; i < ncolors; ++i) {
   674             colors[i].r = entries[i].r;
   675             colors[i].g = entries[i].g;
   676             colors[i].b = entries[i].b;
   677             colors[i].unused = SDL_ALPHA_OPAQUE;
   678         }
   679         return 0;
   680     } else {
   681         return SDL_SetError("YUV textures don't have a palette");
   682     }
   683   error:
   684     return -1;
   685 }
   686 
   687 static int
   688 DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   689 {
   690     return 0;
   691 }
   692 
   693 static int
   694 DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   695 {
   696     return 0;
   697 }
   698 
   699 static int
   700 DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   701 {
   702     switch (texture->blendMode) {
   703     case SDL_BLENDMODE_NONE:
   704     /* case SDL_BLENDMODE_MASK: */
   705     case SDL_BLENDMODE_BLEND:
   706     case SDL_BLENDMODE_ADD:
   707     case SDL_BLENDMODE_MOD:
   708         return 0;
   709     default:
   710         texture->blendMode = SDL_BLENDMODE_NONE;
   711         return SDL_Unsupported();
   712     }
   713 }
   714 
   715 static int
   716 DirectFB_SetDrawBlendMode(SDL_Renderer * renderer)
   717 {
   718     switch (renderer->blendMode) {
   719     case SDL_BLENDMODE_NONE:
   720     /* case SDL_BLENDMODE_MASK: */
   721     case SDL_BLENDMODE_BLEND:
   722     case SDL_BLENDMODE_ADD:
   723     case SDL_BLENDMODE_MOD:
   724         return 0;
   725     default:
   726         renderer->blendMode = SDL_BLENDMODE_NONE;
   727         return SDL_Unsupported();
   728     }
   729 }
   730 
   731 #if 0
   732 static int
   733 DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   734 {
   735 #if (DFB_VERSION_ATLEAST(1,2,0))
   736 
   737     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   738 
   739     switch (texture->scaleMode) {
   740     case SDL_SCALEMODE_NONE:
   741     case SDL_SCALEMODE_FAST:
   742         data->render_options = DSRO_NONE;
   743         break;
   744     case SDL_SCALEMODE_SLOW:
   745         data->render_options = DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE;
   746         break;
   747     case SDL_SCALEMODE_BEST:
   748         data->render_options =
   749             DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE | DSRO_ANTIALIAS;
   750         break;
   751     default:
   752         data->render_options = DSRO_NONE;
   753         texture->scaleMode = SDL_SCALEMODE_NONE;
   754         return SDL_Unsupported();
   755     }
   756 #endif
   757     return 0;
   758 }
   759 #endif
   760 
   761 static int
   762 DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   763                        const SDL_Rect * rect, const void *pixels, int pitch)
   764 {
   765     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   766     Uint8 *dpixels;
   767     int dpitch;
   768     Uint8 *src, *dst;
   769     int row;
   770     size_t length;
   771     int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format));
   772     /* FIXME: SDL_BYTESPERPIXEL(texture->format) broken for yuv yv12 3 planes */
   773 
   774     DirectFB_ActivateRenderer(renderer);
   775 
   776     if ((texture->format == SDL_PIXELFORMAT_YV12) ||
   777         (texture->format == SDL_PIXELFORMAT_IYUV)) {
   778         bpp = 1;
   779     }
   780 
   781     SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
   782                                          DSLF_WRITE | DSLF_READ,
   783                                          ((void **) &dpixels), &dpitch));
   784     src = (Uint8 *) pixels;
   785     dst = (Uint8 *) dpixels + rect->y * dpitch + rect->x * bpp;
   786     length = rect->w * bpp;
   787     for (row = 0; row < rect->h; ++row) {
   788         SDL_memcpy(dst, src, length);
   789         src += pitch;
   790         dst += dpitch;
   791     }
   792     /* copy other planes for 3 plane formats */
   793     if ((texture->format == SDL_PIXELFORMAT_YV12) ||
   794         (texture->format == SDL_PIXELFORMAT_IYUV)) {
   795         src = (Uint8 *) pixels + texture->h * pitch;
   796         dst = (Uint8 *) dpixels + texture->h * dpitch + rect->y * dpitch / 4 + rect->x * bpp / 2;
   797         for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) {
   798             SDL_memcpy(dst, src, length / 2);
   799             src += pitch / 2;
   800             dst += dpitch / 2;
   801         }
   802         src = (Uint8 *) pixels + texture->h * pitch + texture->h * pitch / 4;
   803         dst = (Uint8 *) dpixels + texture->h * dpitch + texture->h * dpitch / 4 + rect->y * dpitch / 4 + rect->x * bpp / 2;
   804         for (row = 0; row < rect->h / 2 + (rect->h & 1); ++row) {
   805             SDL_memcpy(dst, src, length / 2);
   806             src += pitch / 2;
   807             dst += dpitch / 2;
   808         }
   809     }
   810     SDL_DFB_CHECKERR(data->surface->Unlock(data->surface));
   811     data->isDirty = 0;
   812     return 0;
   813   error:
   814     return 1;
   815 
   816 }
   817 
   818 static int
   819 DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   820                      const SDL_Rect * rect, void **pixels, int *pitch)
   821 {
   822     DirectFB_TextureData *texturedata =
   823         (DirectFB_TextureData *) texture->driverdata;
   824 
   825     DirectFB_ActivateRenderer(renderer);
   826 
   827 #if 0
   828     if (markDirty) {
   829         SDL_AddDirtyRect(&texturedata->dirty, rect);
   830     }
   831 #endif
   832 
   833     if (texturedata->display) {
   834         void *fdata;
   835         int fpitch;
   836 
   837         SDL_DFB_CHECKERR(texturedata->surface->Lock(texturedata->surface,
   838                                                     DSLF_WRITE | DSLF_READ,
   839                                                     &fdata, &fpitch));
   840         *pitch = fpitch;
   841         *pixels = fdata;
   842     } else {
   843         *pixels =
   844             (void *) ((Uint8 *) texturedata->pixels +
   845                       rect->y * texturedata->pitch +
   846                       rect->x * DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format)));
   847         *pitch = texturedata->pitch;
   848         texturedata->isDirty = 1;
   849     }
   850     return 0;
   851 
   852   error:
   853     return -1;
   854 }
   855 
   856 static void
   857 DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   858 {
   859     DirectFB_TextureData *texturedata =
   860         (DirectFB_TextureData *) texture->driverdata;
   861 
   862     DirectFB_ActivateRenderer(renderer);
   863 
   864     if (texturedata->display) {
   865         SDL_DFB_CHECK(texturedata->surface->Unlock(texturedata->surface));
   866         texturedata->pixels = NULL;
   867     }
   868 }
   869 
   870 #if 0
   871 static void
   872 DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   873                       int numrects, const SDL_Rect * rects)
   874 {
   875     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   876     int i;
   877 
   878     for (i = 0; i < numrects; ++i) {
   879         SDL_AddDirtyRect(&data->dirty, &rects[i]);
   880     }
   881 }
   882 #endif
   883 
   884 static int DirectFB_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
   885 {
   886     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   887     DirectFB_TextureData *tex_data = NULL;
   888 
   889     DirectFB_ActivateRenderer(renderer);
   890     if (texture) {
   891         tex_data = (DirectFB_TextureData *) texture->driverdata;
   892         data->target = tex_data->surface;
   893     } else {
   894         data->target = get_dfb_surface(data->window);
   895     }
   896     data->lastBlendMode = 0;
   897     return 0;
   898 }
   899 
   900 
   901 static int
   902 PrepareDraw(SDL_Renderer * renderer)
   903 {
   904     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   905     IDirectFBSurface *destsurf = data->target;
   906 
   907     Uint8 r, g, b, a;
   908 
   909     r = renderer->r;
   910     g = renderer->g;
   911     b = renderer->b;
   912     a = renderer->a;
   913 
   914     SetBlendMode(data, renderer->blendMode, NULL);
   915     SDL_DFB_CHECKERR(destsurf->SetDrawingFlags(destsurf, data->drawFlags));
   916 
   917     switch (renderer->blendMode) {
   918     case SDL_BLENDMODE_NONE:
   919     /* case SDL_BLENDMODE_MASK: */
   920     case SDL_BLENDMODE_BLEND:
   921         break;
   922     case SDL_BLENDMODE_ADD:
   923     case SDL_BLENDMODE_MOD:
   924         r = ((int) r * (int) a) / 255;
   925         g = ((int) g * (int) a) / 255;
   926         b = ((int) b * (int) a) / 255;
   927         a = 255;
   928         break;
   929     }
   930 
   931     SDL_DFB_CHECKERR(destsurf->SetColor(destsurf, r, g, b, a));
   932     return 0;
   933   error:
   934     return -1;
   935 }
   936 
   937 static int DirectFB_RenderDrawPoints(SDL_Renderer * renderer,
   938                                 const SDL_FPoint * points, int count)
   939 {
   940     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   941     IDirectFBSurface *destsurf = data->target;
   942     DFBRegion clip_region;
   943     int i;
   944 
   945     DirectFB_ActivateRenderer(renderer);
   946 
   947     PrepareDraw(renderer);
   948     destsurf->GetClip(destsurf, &clip_region);
   949     for (i=0; i < count; i++) {
   950         int x = points[i].x + clip_region.x1;
   951         int y = points[i].y + clip_region.y1;
   952         SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, x, y, x, y));
   953     }
   954     return 0;
   955   error:
   956     return -1;
   957 }
   958 
   959 static int DirectFB_RenderDrawLines(SDL_Renderer * renderer,
   960                                const SDL_FPoint * points, int count)
   961 {
   962     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   963     IDirectFBSurface *destsurf = data->target;
   964     DFBRegion clip_region;
   965     int i;
   966 
   967     DirectFB_ActivateRenderer(renderer);
   968 
   969     PrepareDraw(renderer);
   970     /* Use antialiasing when available */
   971 #if (DFB_VERSION_ATLEAST(1,2,0))
   972     SDL_DFB_CHECKERR(destsurf->SetRenderOptions(destsurf, DSRO_ANTIALIAS));
   973 #endif
   974 
   975     destsurf->GetClip(destsurf, &clip_region);
   976     for (i=0; i < count - 1; i++) {
   977         int x1 = points[i].x + clip_region.x1;
   978         int y1 = points[i].y + clip_region.y1;
   979         int x2 = points[i + 1].x + clip_region.x1;
   980         int y2 = points[i + 1].y + clip_region.y1;
   981         SDL_DFB_CHECKERR(destsurf->DrawLine(destsurf, x1, y1, x2, y2));
   982     }
   983 
   984     return 0;
   985   error:
   986     return -1;
   987 }
   988 
   989 static int
   990 DirectFB_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
   991 {
   992     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   993     IDirectFBSurface *destsurf = data->target;
   994     DFBRegion clip_region;
   995     int i;
   996 
   997     DirectFB_ActivateRenderer(renderer);
   998 
   999     PrepareDraw(renderer);
  1000 
  1001     destsurf->GetClip(destsurf, &clip_region);
  1002     for (i=0; i<count; i++) {
  1003         SDL_Rect dst = {rects[i]->x, rects[i]->y, rects[i]->w, rects[i]->h};
  1004         dst.x += clip_region.x1;
  1005         dst.y += clip_region.y1;
  1006         SDL_DFB_CHECKERR(destsurf->DrawRectangle(destsurf, dst.x, dst.y,
  1007                 dst.w, dst.h));
  1008     }
  1009 
  1010     return 0;
  1011   error:
  1012     return -1;
  1013 }
  1014 
  1015 static int
  1016 DirectFB_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
  1017 {
  1018     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1019     IDirectFBSurface *destsurf = data->target;
  1020     DFBRegion clip_region;
  1021     int i;
  1022 
  1023     DirectFB_ActivateRenderer(renderer);
  1024 
  1025     PrepareDraw(renderer);
  1026 
  1027     destsurf->GetClip(destsurf, &clip_region);
  1028     for (i=0; i<count; i++) {
  1029         SDL_Rect dst = {rects[i].x, rects[i].y, rects[i].w, rects[i].h};
  1030         dst.x += clip_region.x1;
  1031         dst.y += clip_region.y1;
  1032         SDL_DFB_CHECKERR(destsurf->FillRectangle(destsurf, dst.x, dst.y,
  1033                 dst.w, dst.h));
  1034     }
  1035 
  1036     return 0;
  1037   error:
  1038     return -1;
  1039 }
  1040 
  1041 static int
  1042 DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
  1043                     const SDL_Rect * srcrect, const SDL_FRect * dstrect)
  1044 {
  1045     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1046     IDirectFBSurface *destsurf = data->target;
  1047     DirectFB_TextureData *texturedata =
  1048         (DirectFB_TextureData *) texture->driverdata;
  1049     Uint8 alpha, r, g, b;
  1050     DFBRegion clip_region;
  1051     DFBRectangle sr, dr;
  1052 
  1053     DirectFB_ActivateRenderer(renderer);
  1054 
  1055     SDLtoDFBRect(srcrect, &sr);
  1056     SDLtoDFBRect_Float(dstrect, &dr);
  1057 
  1058     destsurf->GetClip(destsurf, &clip_region);
  1059     dr.x += clip_region.x1;
  1060     dr.y += clip_region.y1;
  1061 
  1062     if (texturedata->display) {
  1063         int px, py;
  1064         SDL_Window *window = renderer->window;
  1065         IDirectFBWindow *dfbwin = get_dfb_window(window);
  1066         SDL_DFB_WINDOWDATA(window);
  1067         SDL_VideoDisplay *display = texturedata->display;
  1068         DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
  1069 
  1070         SDL_DFB_CHECKERR(dispdata->
  1071                          vidlayer->SetSourceRectangle(dispdata->vidlayer,
  1072                                                       sr.x, sr.y, sr.w, sr.h));
  1073         dfbwin->GetPosition(dfbwin, &px, &py);
  1074         px += windata->client.x;
  1075         py += windata->client.y;
  1076         SDL_DFB_CHECKERR(dispdata->
  1077                          vidlayer->SetScreenRectangle(dispdata->vidlayer,
  1078                                                       px + dr.x,
  1079                                                       py + dr.y,
  1080                                                       dr.w,
  1081                                                       dr.h));
  1082     } else {
  1083         DFBSurfaceBlittingFlags flags = 0;
  1084 
  1085 #if 0
  1086         if (texturedata->dirty.list) {
  1087             SDL_DirtyRect *dirty;
  1088             void *pixels;
  1089             int bpp = DFB_BYTES_PER_PIXEL(DirectFB_SDLToDFBPixelFormat(texture->format));
  1090             int pitch = texturedata->pitch;
  1091 
  1092             for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
  1093                 SDL_Rect *rect = &dirty->rect;
  1094                 pixels =
  1095                     (void *) ((Uint8 *) texturedata->pixels +
  1096                               rect->y * pitch + rect->x * bpp);
  1097                 DirectFB_UpdateTexture(renderer, texture, rect,
  1098                                        pixels,
  1099                                        texturedata->pitch);
  1100             }
  1101             SDL_ClearDirtyRects(&texturedata->dirty);
  1102         }
  1103 #endif
  1104         if (texturedata->isDirty)
  1105         {
  1106             SDL_Rect rect;
  1107 
  1108             rect.x = 0;
  1109             rect.y = 0;
  1110             rect.w = texture->w;
  1111             rect.h = texture->h;
  1112 
  1113             DirectFB_UpdateTexture(renderer, texture, &rect, texturedata->pixels, texturedata->pitch);
  1114         }
  1115 
  1116         alpha = r = g = b = 0xff;
  1117         if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA){
  1118             alpha = texture->a;
  1119             flags |= DSBLIT_BLEND_COLORALPHA;
  1120         }
  1121 
  1122         if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
  1123             r = texture->r;
  1124             g = texture->g;
  1125             b = texture->b;
  1126             flags |= DSBLIT_COLORIZE;
  1127         }
  1128         SDL_DFB_CHECKERR(destsurf->
  1129                          SetColor(destsurf, r, g, b, alpha));
  1130 
  1131         /* ???? flags |= DSBLIT_SRC_PREMULTCOLOR; */
  1132 
  1133         SetBlendMode(data, texture->blendMode, texturedata);
  1134 
  1135         SDL_DFB_CHECKERR(destsurf->SetBlittingFlags(destsurf,
  1136                                                     data->blitFlags | flags));
  1137 
  1138 #if (DFB_VERSION_ATLEAST(1,2,0))
  1139         SDL_DFB_CHECKERR(destsurf->SetRenderOptions(destsurf,
  1140                                                     texturedata->
  1141                                                     render_options));
  1142 #endif
  1143 
  1144         if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
  1145             SDL_DFB_CHECKERR(destsurf->Blit(destsurf,
  1146                                             texturedata->surface,
  1147                                             &sr, dr.x, dr.y));
  1148         } else {
  1149             SDL_DFB_CHECKERR(destsurf->StretchBlit(destsurf,
  1150                                                    texturedata->surface,
  1151                                                    &sr, &dr));
  1152         }
  1153     }
  1154     return 0;
  1155   error:
  1156     return -1;
  1157 }
  1158 
  1159 static void
  1160 DirectFB_RenderPresent(SDL_Renderer * renderer)
  1161 {
  1162     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1163     SDL_Window *window = renderer->window;
  1164     SDL_DFB_WINDOWDATA(window);
  1165     SDL_ShapeData *shape_data = (window->shaper ? window->shaper->driverdata : NULL);
  1166 
  1167     DirectFB_ActivateRenderer(renderer);
  1168 
  1169     if (shape_data && shape_data->surface) {
  1170         /* saturate the window surface alpha channel */
  1171         SDL_DFB_CHECK(windata->window_surface->SetSrcBlendFunction(windata->window_surface, DSBF_ONE));
  1172         SDL_DFB_CHECK(windata->window_surface->SetDstBlendFunction(windata->window_surface, DSBF_ONE));
  1173         SDL_DFB_CHECK(windata->window_surface->SetDrawingFlags(windata->window_surface, DSDRAW_BLEND));
  1174         SDL_DFB_CHECK(windata->window_surface->SetColor(windata->window_surface, 0, 0, 0, 0xff));
  1175         SDL_DFB_CHECK(windata->window_surface->FillRectangle(windata->window_surface, 0,0, windata->size.w, windata->size.h));
  1176 
  1177         /* blit the mask */
  1178         SDL_DFB_CHECK(windata->surface->SetSrcBlendFunction(windata->surface, DSBF_DESTCOLOR));
  1179         SDL_DFB_CHECK(windata->surface->SetDstBlendFunction(windata->surface, DSBF_ZERO));
  1180         SDL_DFB_CHECK(windata->surface->SetBlittingFlags(windata->surface, DSBLIT_BLEND_ALPHACHANNEL));
  1181 #if (DFB_VERSION_ATLEAST(1,2,0))
  1182         SDL_DFB_CHECK(windata->surface->SetRenderOptions(windata->surface, DSRO_NONE));
  1183 #endif
  1184         SDL_DFB_CHECK(windata->surface->Blit(windata->surface, shape_data->surface, NULL, 0, 0));
  1185     }
  1186 
  1187     /* Send the data to the display */
  1188     SDL_DFB_CHECK(windata->window_surface->Flip(windata->window_surface, NULL,
  1189                                                 data->flipflags));
  1190 }
  1191 
  1192 static void
  1193 DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1194 {
  1195     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
  1196 
  1197     DirectFB_ActivateRenderer(renderer);
  1198 
  1199     if (!data) {
  1200         return;
  1201     }
  1202     SDL_DFB_RELEASE(data->palette);
  1203     SDL_DFB_RELEASE(data->surface);
  1204     if (data->display) {
  1205         DFB_DisplayData *dispdata =
  1206             (DFB_DisplayData *) data->display->driverdata;
  1207         dispdata->vidIDinuse = 0;
  1208         /* FIXME: Shouldn't we reset the cooperative level */
  1209         SDL_DFB_CHECK(dispdata->vidlayer->SetCooperativeLevel(dispdata->vidlayer,
  1210                                                 DLSCL_ADMINISTRATIVE));
  1211         SDL_DFB_RELEASE(dispdata->vidlayer);
  1212     }
  1213     SDL_DFB_FREE(data->pixels);
  1214     SDL_free(data);
  1215     texture->driverdata = NULL;
  1216 }
  1217 
  1218 static void
  1219 DirectFB_DestroyRenderer(SDL_Renderer * renderer)
  1220 {
  1221     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1222     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(data->window);
  1223 #if 0
  1224     if (display->palette) {
  1225         SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, data);
  1226     }
  1227 #endif
  1228 
  1229     if (data) {
  1230         SDL_free(data);
  1231     }
  1232     SDL_free(renderer);
  1233 }
  1234 
  1235 static int
  1236 DirectFB_UpdateViewport(SDL_Renderer * renderer)
  1237 {
  1238     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1239     IDirectFBSurface *winsurf = data->target;
  1240     DFBRegion dreg;
  1241 
  1242     dreg.x1 = renderer->viewport.x;
  1243     dreg.y1 = renderer->viewport.y;
  1244     dreg.x2 = dreg.x1 + renderer->viewport.w - 1;
  1245     dreg.y2 = dreg.y1 + renderer->viewport.h - 1;
  1246 
  1247     winsurf->SetClip(winsurf, &dreg);
  1248     return 0;
  1249 }
  1250 
  1251 static int
  1252 DirectFB_UpdateClipRect(SDL_Renderer * renderer)
  1253 {
  1254     const SDL_Rect *rect = &renderer->clip_rect;
  1255     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1256     IDirectFBSurface *destsurf = get_dfb_surface(data->window);
  1257     DFBRegion region;
  1258 
  1259     if (!SDL_RectEmpty(rect)) {
  1260         region.x1 = rect->x;
  1261         region.x2 = rect->x + rect->w;
  1262         region.y1 = rect->y;
  1263         region.y2 = rect->y + rect->h;
  1264         SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, &region));
  1265     } else {
  1266         SDL_DFB_CHECKERR(destsurf->SetClip(destsurf, NULL));
  1267     }
  1268     return 0;
  1269   error:
  1270     return -1;
  1271 }
  1272 
  1273 static int
  1274 DirectFB_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1275                      Uint32 format, void * pixels, int pitch)
  1276 {
  1277     Uint32 sdl_format;
  1278     void * laypixels;
  1279     int laypitch;
  1280     DFBSurfacePixelFormat dfb_format;
  1281     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1282     IDirectFBSurface *winsurf = data->target;
  1283 
  1284     DirectFB_ActivateRenderer(renderer);
  1285 
  1286     winsurf->GetPixelFormat(winsurf, &dfb_format);
  1287     sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format);
  1288     winsurf->Lock(winsurf, DSLF_READ, (void **) &laypixels, &laypitch);
  1289 
  1290     laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) );
  1291     SDL_ConvertPixels(rect->w, rect->h,
  1292                       sdl_format, laypixels, laypitch,
  1293                       format, pixels, pitch);
  1294 
  1295     winsurf->Unlock(winsurf);
  1296 
  1297     return 0;
  1298 }
  1299 
  1300 #if 0
  1301 static int
  1302 DirectFB_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1303                       Uint32 format, const void * pixels, int pitch)
  1304 {
  1305     SDL_Window *window = renderer->window;
  1306     SDL_DFB_WINDOWDATA(window);
  1307     Uint32 sdl_format;
  1308     void * laypixels;
  1309     int laypitch;
  1310     DFBSurfacePixelFormat dfb_format;
  1311 
  1312     SDL_DFB_CHECK(windata->surface->GetPixelFormat(windata->surface, &dfb_format));
  1313     sdl_format = DirectFB_DFBToSDLPixelFormat(dfb_format);
  1314 
  1315     SDL_DFB_CHECK(windata->surface->Lock(windata->surface, DSLF_WRITE, (void **) &laypixels, &laypitch));
  1316 
  1317     laypixels += (rect->y * laypitch + rect->x * SDL_BYTESPERPIXEL(sdl_format) );
  1318     SDL_ConvertPixels(rect->w, rect->h,
  1319                       format, pixels, pitch,
  1320                       sdl_format, laypixels, laypitch);
  1321 
  1322     SDL_DFB_CHECK(windata->surface->Unlock(windata->surface));
  1323 
  1324     return 0;
  1325 }
  1326 #endif
  1327 
  1328 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
  1329 
  1330 /* vi: set ts=4 sw=4 expandtab: */