src/video/directfb/SDL_DirectFB_render.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 10 Jan 2009 21:50:26 +0000
changeset 3013 8cc00819c8d6
parent 3011 8f4ed5ec2b06
child 3023 d72a0dd80e8b
permissions -rw-r--r--
Reverted Bob's indent checkin
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21     
    22     SDL1.3 implementation by couriersud@arcor.de
    23     
    24 */
    25 #include "SDL_config.h"
    26 
    27 #include "SDL_DirectFB_video.h"
    28 #include "SDL_DirectFB_render.h"
    29 #include "../SDL_rect_c.h"
    30 #include "../SDL_yuv_sw_c.h"
    31 
    32 /* the following is not yet tested ... */
    33 #define USE_DISPLAY_PALETTE			(0)
    34 
    35 /* GDI renderer implementation */
    36 
    37 static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window,
    38                                              Uint32 flags);
    39 static int DirectFB_DisplayModeChanged(SDL_Renderer * renderer);
    40 static int DirectFB_ActivateRenderer(SDL_Renderer * renderer);
    41 static int DirectFB_CreateTexture(SDL_Renderer * renderer,
    42                                   SDL_Texture * texture);
    43 static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
    44                                        SDL_Texture * texture, void **pixels,
    45                                        int *pitch);
    46 static int DirectFB_SetTexturePalette(SDL_Renderer * renderer,
    47                                       SDL_Texture * texture,
    48                                       const SDL_Color * colors,
    49                                       int firstcolor, int ncolors);
    50 static int DirectFB_GetTexturePalette(SDL_Renderer * renderer,
    51                                       SDL_Texture * texture,
    52                                       SDL_Color * colors, int firstcolor,
    53                                       int ncolors);
    54 static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,
    55                                        SDL_Texture * texture);
    56 static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer,
    57                                        SDL_Texture * texture);
    58 static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,
    59                                         SDL_Texture * texture);
    60 static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer,
    61                                         SDL_Texture * texture);
    62 static int DirectFB_UpdateTexture(SDL_Renderer * renderer,
    63                                   SDL_Texture * texture,
    64                                   const SDL_Rect * rect, const void *pixels,
    65                                   int pitch);
    66 static int DirectFB_LockTexture(SDL_Renderer * renderer,
    67                                 SDL_Texture * texture, const SDL_Rect * rect,
    68                                 int markDirty, void **pixels, int *pitch);
    69 static void DirectFB_UnlockTexture(SDL_Renderer * renderer,
    70                                    SDL_Texture * texture);
    71 static void DirectFB_DirtyTexture(SDL_Renderer * renderer,
    72                                   SDL_Texture * texture, int numrects,
    73                                   const SDL_Rect * rects);
    74 static int DirectFB_RenderPoint(SDL_Renderer * renderer, int x, int y);
    75 static int DirectFB_RenderLine(SDL_Renderer * renderer, int x1, int y1,
    76                                int x2, int y2);
    77 static int DirectFB_RenderFill(SDL_Renderer * renderer,
    78                                const SDL_Rect * rect);
    79 static int DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    80                                const SDL_Rect * srcrect,
    81                                const SDL_Rect * dstrect);
    82 static void DirectFB_RenderPresent(SDL_Renderer * renderer);
    83 static void DirectFB_DestroyTexture(SDL_Renderer * renderer,
    84                                     SDL_Texture * texture);
    85 static void DirectFB_DestroyRenderer(SDL_Renderer * renderer);
    86 
    87 SDL_RenderDriver DirectFB_RenderDriver = {
    88     DirectFB_CreateRenderer,
    89     {
    90      "directfb",
    91      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
    92       SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
    93       SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_PRESENTDISCARD |
    94       SDL_RENDERER_ACCELERATED),
    95      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
    96       SDL_TEXTUREMODULATE_ALPHA),
    97      (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
    98       SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
    99      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
   100       SDL_TEXTURESCALEMODE_SLOW | SDL_TEXTURESCALEMODE_BEST),
   101      14,
   102      {
   103       SDL_PIXELFORMAT_INDEX4LSB,
   104       SDL_PIXELFORMAT_INDEX8,
   105       SDL_PIXELFORMAT_RGB332,
   106       SDL_PIXELFORMAT_RGB555,
   107       SDL_PIXELFORMAT_RGB565,
   108       SDL_PIXELFORMAT_RGB888,
   109       SDL_PIXELFORMAT_ARGB8888,
   110       SDL_PIXELFORMAT_ARGB4444,
   111       SDL_PIXELFORMAT_ARGB1555,
   112       SDL_PIXELFORMAT_RGB24,
   113       SDL_PIXELFORMAT_YV12,
   114       SDL_PIXELFORMAT_IYUV,
   115       SDL_PIXELFORMAT_YUY2,
   116       SDL_PIXELFORMAT_UYVY},
   117      0,
   118      0}
   119 };
   120 
   121 typedef struct
   122 {
   123     IDirectFBSurface *surface;
   124     DFBSurfaceFlipFlags flipflags;
   125     int isyuvdirect;
   126     int size_changed;
   127     int lastBlendMode;
   128     DFBSurfaceBlittingFlags blitFlags;
   129     DFBSurfaceDrawingFlags drawFlags;
   130 } DirectFB_RenderData;
   131 
   132 typedef struct
   133 {
   134     IDirectFBSurface *surface;
   135     Uint32 format;
   136     void *pixels;
   137     int pitch;
   138     IDirectFBPalette *palette;
   139     SDL_VideoDisplay *display;
   140     SDL_DirtyRectList dirty;
   141 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   142     DFBSurfaceRenderOptions render_options;
   143 #endif
   144 } DirectFB_TextureData;
   145 
   146 static __inline__ void
   147 SDLtoDFBRect(const SDL_Rect * sr, DFBRectangle * dr)
   148 {
   149     dr->x = sr->x;
   150     dr->y = sr->y;
   151     dr->h = sr->h;
   152     dr->w = sr->w;
   153 }
   154 
   155 
   156 static int
   157 TextureHasAlpha(DirectFB_TextureData * data)
   158 {
   159     /* Drawing primitive ? */
   160     if (!data)
   161         return 0;
   162     switch (data->format) {
   163     case SDL_PIXELFORMAT_INDEX4LSB:
   164     case SDL_PIXELFORMAT_ARGB4444:
   165     case SDL_PIXELFORMAT_ARGB1555:
   166     case SDL_PIXELFORMAT_ARGB8888:
   167     case SDL_PIXELFORMAT_RGBA8888:
   168     case SDL_PIXELFORMAT_ABGR8888:
   169     case SDL_PIXELFORMAT_BGRA8888:
   170     case SDL_PIXELFORMAT_ARGB2101010:
   171         return 1;
   172     default:
   173         return 0;
   174     }
   175 }
   176 
   177 static void
   178 SetBlendMode(DirectFB_RenderData * data, int blendMode,
   179              DirectFB_TextureData * source)
   180 {
   181     //FIXME: check for format change
   182     if (1 || data->lastBlendMode != blendMode) {
   183         switch (blendMode) {
   184         case SDL_BLENDMODE_NONE:
   185                                            /**< No blending */
   186             data->blitFlags = DSBLIT_NOFX;
   187             data->drawFlags = DSDRAW_NOFX;
   188             data->surface->SetSrcBlendFunction(data->surface, DSBF_ONE);
   189             data->surface->SetDstBlendFunction(data->surface, DSBF_ZERO);
   190             break;
   191         case SDL_BLENDMODE_MASK:
   192             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   193             data->drawFlags = DSDRAW_BLEND;
   194             data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
   195             data->surface->SetDstBlendFunction(data->surface,
   196                                                DSBF_INVSRCALPHA);
   197             break;
   198         case SDL_BLENDMODE_BLEND:
   199             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   200             data->drawFlags = DSDRAW_BLEND;
   201             data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
   202             data->surface->SetDstBlendFunction(data->surface,
   203                                                DSBF_INVSRCALPHA);
   204             break;
   205         case SDL_BLENDMODE_ADD:
   206             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   207             data->drawFlags = DSDRAW_BLEND;
   208             // FIXME: SRCALPHA kills performance on radeon ...
   209             // It will be cheaper to copy the surface to
   210             // a temporay surface and premultiply 
   211             if (source && TextureHasAlpha(source))
   212                 data->surface->SetSrcBlendFunction(data->surface,
   213                                                    DSBF_SRCALPHA);
   214             else
   215                 data->surface->SetSrcBlendFunction(data->surface, DSBF_ONE);
   216             data->surface->SetDstBlendFunction(data->surface, DSBF_ONE);
   217             break;
   218         case SDL_BLENDMODE_MOD:
   219             data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
   220             data->drawFlags = DSDRAW_BLEND;
   221             data->surface->SetSrcBlendFunction(data->surface, DSBF_DESTCOLOR);
   222             data->surface->SetDstBlendFunction(data->surface, DSBF_ZERO);
   223             break;
   224         }
   225         data->lastBlendMode = blendMode;
   226     }
   227 }
   228 
   229 void
   230 DirectFB_AddRenderDriver(_THIS)
   231 {
   232     int i;
   233     for (i = 0; i < _this->num_displays; i++)
   234         SDL_AddRenderDriver(i, &DirectFB_RenderDriver);
   235 }
   236 
   237 static int
   238 DisplayPaletteChanged(void *userdata, SDL_Palette * palette)
   239 {
   240 #if USE_DISPLAY_PALETTE
   241     DirectFB_RenderData *data = (DirectFB_RenderData *) userdata;
   242     IDirectFBPalette *surfpal;
   243 
   244     int ret;
   245     int i;
   246     int ncolors;
   247     DFBColor entries[256];
   248 
   249     SDL_DFB_CHECKERR(data->surface->GetPalette(data->surface, &surfpal));
   250 
   251     /* FIXME: number of colors */
   252     ncolors = (palette->ncolors < 256 ? palette->ncolors : 256);
   253 
   254     for (i = 0; i < ncolors; ++i) {
   255         entries[i].r = palette->colors[i].r;
   256         entries[i].g = palette->colors[i].g;
   257         entries[i].b = palette->colors[i].b;
   258         entries[i].a = palette->colors[i].unused;
   259     }
   260     SDL_DFB_CHECKERR(surfpal->SetEntries(surfpal, entries, ncolors, 0));
   261     return 0;
   262   error:
   263 #endif
   264     return -1;
   265 }
   266 
   267 
   268 SDL_Renderer *
   269 DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
   270 {
   271     SDL_DFB_WINDOWDATA(window);
   272     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   273     SDL_Renderer *renderer = NULL;
   274     DirectFB_RenderData *data = NULL;
   275     DFBResult ret;
   276     DFBSurfaceCapabilities scaps;
   277     char *p;
   278 
   279     SDL_DFB_CALLOC(renderer, 1, sizeof(*renderer));
   280     SDL_DFB_CALLOC(data, 1, sizeof(*data));
   281 
   282     renderer->DisplayModeChanged = DirectFB_DisplayModeChanged;
   283     renderer->ActivateRenderer = DirectFB_ActivateRenderer;
   284     renderer->CreateTexture = DirectFB_CreateTexture;
   285     renderer->QueryTexturePixels = DirectFB_QueryTexturePixels;
   286     renderer->SetTexturePalette = DirectFB_SetTexturePalette;
   287     renderer->GetTexturePalette = DirectFB_GetTexturePalette;
   288     renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod;
   289     renderer->SetTextureColorMod = DirectFB_SetTextureColorMod;
   290     renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode;
   291     renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
   292     renderer->UpdateTexture = DirectFB_UpdateTexture;
   293     renderer->LockTexture = DirectFB_LockTexture;
   294     renderer->UnlockTexture = DirectFB_UnlockTexture;
   295     renderer->DirtyTexture = DirectFB_DirtyTexture;
   296     renderer->RenderPoint = DirectFB_RenderPoint;
   297     renderer->RenderLine = DirectFB_RenderLine;
   298     renderer->RenderFill = DirectFB_RenderFill;
   299     renderer->RenderCopy = DirectFB_RenderCopy;
   300     renderer->RenderPresent = DirectFB_RenderPresent;
   301     renderer->DestroyTexture = DirectFB_DestroyTexture;
   302     renderer->DestroyRenderer = DirectFB_DestroyRenderer;
   303     renderer->info = DirectFB_RenderDriver.info;
   304     renderer->window = window->id;      /* SDL window id */
   305     renderer->driverdata = data;
   306 
   307     renderer->info.flags =
   308         SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTDISCARD;
   309 
   310     data->surface = windata->surface;
   311     data->surface->AddRef(data->surface);
   312 
   313     data->flipflags = DSFLIP_PIPELINE | DSFLIP_BLIT;
   314 
   315     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   316         data->flipflags |= DSFLIP_WAITFORSYNC;
   317         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   318     } else
   319         data->flipflags |= DSFLIP_ONSYNC;
   320 
   321     SDL_DFB_CHECKERR(data->surface->GetCapabilities(data->surface, &scaps));
   322     if (scaps & DSCAPS_DOUBLE)
   323         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
   324     else if (scaps & DSCAPS_TRIPLE)
   325         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
   326     else
   327         renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
   328 
   329     data->isyuvdirect = 0;      /* default is off! */
   330     p = getenv(DFBENV_USE_YUV_DIRECT);
   331     if (p)
   332         data->isyuvdirect = atoi(p);
   333 
   334     /* Set up a palette watch on the display palette */
   335     if (display->palette) {
   336         SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data);
   337     }
   338 
   339     return renderer;
   340 
   341   error:
   342     SDL_DFB_FREE(renderer);
   343     SDL_DFB_FREE(data);
   344     return NULL;
   345 }
   346 
   347 static DFBSurfacePixelFormat
   348 SDLToDFBPixelFormat(Uint32 format)
   349 {
   350     switch (format) {
   351     case SDL_PIXELFORMAT_INDEX4LSB:
   352         return DSPF_ALUT44;
   353     case SDL_PIXELFORMAT_INDEX8:
   354         return DSPF_LUT8;
   355     case SDL_PIXELFORMAT_RGB332:
   356         return DSPF_RGB332;
   357     case SDL_PIXELFORMAT_RGB555:
   358         return DSPF_ARGB1555;
   359     case SDL_PIXELFORMAT_ARGB4444:
   360         return DSPF_ARGB4444;
   361     case SDL_PIXELFORMAT_ARGB1555:
   362         return DSPF_ARGB1555;
   363     case SDL_PIXELFORMAT_RGB565:
   364         return DSPF_RGB16;
   365     case SDL_PIXELFORMAT_RGB24:
   366         return DSPF_RGB24;
   367     case SDL_PIXELFORMAT_RGB888:
   368         return DSPF_RGB32;
   369     case SDL_PIXELFORMAT_ARGB8888:
   370         return DSPF_ARGB;
   371     case SDL_PIXELFORMAT_YV12:
   372         return DSPF_YV12;       /* Planar mode: Y + V + U  (3 planes) */
   373     case SDL_PIXELFORMAT_IYUV:
   374         return DSPF_I420;       /* Planar mode: Y + U + V  (3 planes) */
   375     case SDL_PIXELFORMAT_YUY2:
   376         return DSPF_YUY2;       /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
   377     case SDL_PIXELFORMAT_UYVY:
   378         return DSPF_UYVY;       /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
   379     case SDL_PIXELFORMAT_YVYU:
   380         return DSPF_UNKNOWN;    /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
   381     case SDL_PIXELFORMAT_INDEX1LSB:
   382         return DSPF_UNKNOWN;
   383     case SDL_PIXELFORMAT_INDEX1MSB:
   384         return DSPF_UNKNOWN;
   385     case SDL_PIXELFORMAT_INDEX4MSB:
   386         return DSPF_UNKNOWN;
   387     case SDL_PIXELFORMAT_RGB444:
   388 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   389         return DSPF_RGB444;
   390 #else
   391         return DSPF_UNKNOWN;
   392 #endif
   393     case SDL_PIXELFORMAT_BGR24:
   394         return DSPF_UNKNOWN;
   395     case SDL_PIXELFORMAT_BGR888:
   396         return DSPF_UNKNOWN;
   397     case SDL_PIXELFORMAT_RGBA8888:
   398         return DSPF_UNKNOWN;
   399     case SDL_PIXELFORMAT_ABGR8888:
   400         return DSPF_UNKNOWN;
   401     case SDL_PIXELFORMAT_BGRA8888:
   402         return DSPF_UNKNOWN;
   403     case SDL_PIXELFORMAT_ARGB2101010:
   404         return DSPF_UNKNOWN;
   405     default:
   406         return DSPF_UNKNOWN;
   407     }
   408 }
   409 
   410 static int
   411 DirectFB_ActivateRenderer(SDL_Renderer * renderer)
   412 {
   413     SDL_DFB_RENDERERDATA(renderer);
   414     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   415     SDL_DFB_WINDOWDATA(window);
   416 
   417     if (renddata->size_changed) {
   418         int cw, ch;
   419         int ret;
   420 
   421         SDL_DFB_CHECKERR(windata->surface->
   422                          GetSize(windata->surface, &cw, &ch));
   423         if (cw != window->w || ch != window->h)
   424             SDL_DFB_CHECKERR(windata->window->
   425                              ResizeSurface(windata->window, window->w,
   426                                            window->h));
   427     }
   428     return 0;
   429   error:
   430     return -1;
   431 }
   432 
   433 static int
   434 DirectFB_DisplayModeChanged(SDL_Renderer * renderer)
   435 {
   436     SDL_DFB_RENDERERDATA(renderer);
   437 
   438     renddata->size_changed = SDL_TRUE;
   439     return 0;
   440 }
   441 
   442 static int
   443 DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
   444 {
   445     SDL_DFB_RENDERERDATA(renderer);
   446     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   447     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   448     SDL_DFB_DEVICEDATA(display->device);
   449     DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   450     DirectFB_TextureData *data = texture->driverdata;
   451     DFBDisplayLayerConfig layconf;
   452     int ret;
   453 
   454     if (renddata->isyuvdirect && (dispdata->vidID >= 0)
   455         && (!dispdata->vidIDinuse)
   456         && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   457         layconf.flags =
   458             DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
   459             DLCONF_SURFACE_CAPS;
   460         layconf.width = texture->w;
   461         layconf.height = texture->h;
   462         layconf.pixelformat = SDLToDFBPixelFormat(data->format);
   463         layconf.surface_caps = DSCAPS_VIDEOONLY | DSCAPS_DOUBLE;
   464 
   465         SDL_DFB_CHECKERR(devdata->dfb->
   466                          GetDisplayLayer(devdata->dfb, dispdata->vidID,
   467                                          &dispdata->vidlayer));
   468         SDL_DFB_CHECKERR(dispdata->vidlayer->
   469                          SetCooperativeLevel(dispdata->vidlayer,
   470                                              DLSCL_EXCLUSIVE));
   471 
   472         if (devdata->use_yuv_underlays) {
   473             ret = dispdata->vidlayer->SetLevel(dispdata->vidlayer, -1);
   474             if (ret != DFB_OK)
   475                 SDL_DFB_DEBUG("Underlay Setlevel not supported\n");
   476         }
   477         SDL_DFB_CHECKERR(dispdata->vidlayer->
   478                          SetConfiguration(dispdata->vidlayer, &layconf));
   479         SDL_DFB_CHECKERR(dispdata->vidlayer->
   480                          GetSurface(dispdata->vidlayer, &data->surface));
   481         dispdata->vidIDinuse = 1;
   482         data->display = display;
   483         return 0;
   484     }
   485     return 1;
   486   error:
   487     if (dispdata->vidlayer) {
   488         SDL_DFB_RELEASE(data->surface);
   489         SDL_DFB_CHECKERR(dispdata->vidlayer->
   490                          SetCooperativeLevel(dispdata->vidlayer,
   491                                              DLSCL_ADMINISTRATIVE));
   492         SDL_DFB_RELEASE(dispdata->vidlayer);
   493     }
   494     return 1;
   495 }
   496 
   497 static int
   498 DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   499 {
   500     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   501     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   502     SDL_DFB_DEVICEDATA(display->device);
   503     DirectFB_TextureData *data;
   504     DFBResult ret;
   505     DFBSurfaceDescription dsc;
   506 
   507     SDL_DFB_CALLOC(data, 1, sizeof(*data));
   508     texture->driverdata = data;
   509 
   510     data->format = texture->format;
   511     data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
   512 
   513     if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
   514         /* fill surface description */
   515         dsc.flags =
   516             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   517         dsc.width = texture->w;
   518         dsc.height = texture->h;
   519         /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
   520          * No DSCAPS_SYSTEMONLY either - let dfb decide
   521          * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
   522          * Depends on other settings as well. Let dfb decide.
   523          */
   524         dsc.caps = DSCAPS_PREMULTIPLIED;
   525 #if 0
   526         if (texture->access == SDL_TEXTUREACCESS_STREAMING)
   527             dsc.caps |= DSCAPS_SYSTEMONLY;
   528         else
   529             dsc.caps |= DSCAPS_VIDEOONLY;
   530 #endif
   531 
   532         /* find the right pixelformat */
   533 
   534         dsc.pixelformat = SDLToDFBPixelFormat(data->format);
   535         if (dsc.pixelformat == DSPF_UNKNOWN) {
   536             SDL_SetError("Unknown pixel format %d\n", data->format);
   537             goto error;
   538         }
   539 
   540         data->pixels = NULL;
   541 
   542         /* Create the surface */
   543         SDL_DFB_CHECKERR(devdata->dfb->
   544                          CreateSurface(devdata->dfb, &dsc, &data->surface));
   545         if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   546             && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   547             SDL_DFB_CHECKERR(data->surface->
   548                              GetPalette(data->surface, &data->palette));
   549         }
   550 
   551     }
   552 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   553     data->render_options = DSRO_NONE;
   554 #endif
   555 
   556     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   557         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   558         SDL_DFB_CALLOC(data->pixels, 1, texture->h * data->pitch);
   559     }
   560 
   561     return 0;
   562 
   563   error:
   564     SDL_DFB_RELEASE(data->palette);
   565     SDL_DFB_RELEASE(data->surface);
   566     SDL_DFB_FREE(texture->driverdata);
   567     return -1;
   568 }
   569 
   570 static int
   571 DirectFB_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   572                             void **pixels, int *pitch)
   573 {
   574     DirectFB_TextureData *texturedata =
   575         (DirectFB_TextureData *) texture->driverdata;
   576 
   577     if (texturedata->display) {
   578         return -1;
   579     } else {
   580         *pixels = texturedata->pixels;
   581         *pitch = texturedata->pitch;
   582     }
   583     return 0;
   584 }
   585 
   586 static int
   587 DirectFB_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   588                            const SDL_Color * colors, int firstcolor,
   589                            int ncolors)
   590 {
   591     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   592     DFBResult ret;
   593 
   594     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   595         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   596         DFBColor entries[256];
   597         int i;
   598 
   599         for (i = 0; i < ncolors; ++i) {
   600             entries[i].r = colors[i].r;
   601             entries[i].g = colors[i].g;
   602             entries[i].b = colors[i].b;
   603             entries[i].a = 0xFF;
   604         }
   605         SDL_DFB_CHECKERR(data->palette->
   606                          SetEntries(data->palette, entries, ncolors,
   607                                     firstcolor));
   608         return 0;
   609     } else {
   610         SDL_SetError("YUV textures don't have a palette");
   611         return -1;
   612     }
   613   error:
   614     return -1;
   615 }
   616 
   617 static int
   618 DirectFB_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   619                            SDL_Color * colors, int firstcolor, int ncolors)
   620 {
   621     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   622     DFBResult ret;
   623 
   624     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   625         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   626         DFBColor entries[256];
   627         int i;
   628 
   629         SDL_DFB_CHECKERR(data->palette->
   630                          GetEntries(data->palette, entries, ncolors,
   631                                     firstcolor));
   632 
   633         for (i = 0; i < ncolors; ++i) {
   634             colors[i].r = entries[i].r;
   635             colors[i].g = entries[i].g;
   636             colors[i].b = entries[i].b;
   637             colors->unused = SDL_ALPHA_OPAQUE;
   638         }
   639         return 0;
   640     } else {
   641         SDL_SetError("YUV textures don't have a palette");
   642         return -1;
   643     }
   644   error:
   645     return -1;
   646 }
   647 
   648 static int
   649 DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   650 {
   651     return 0;
   652 }
   653 
   654 static int
   655 DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   656 {
   657     return 0;
   658 }
   659 
   660 static int
   661 DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   662 {
   663     switch (texture->blendMode) {
   664     case SDL_BLENDMODE_NONE:
   665     case SDL_BLENDMODE_MASK:
   666     case SDL_BLENDMODE_BLEND:
   667     case SDL_BLENDMODE_ADD:
   668     case SDL_BLENDMODE_MOD:
   669         return 0;
   670     default:
   671         SDL_Unsupported();
   672         texture->blendMode = SDL_BLENDMODE_NONE;
   673         return -1;
   674     }
   675 }
   676 
   677 static int
   678 DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   679 {
   680 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   681 
   682     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   683 
   684     switch (texture->scaleMode) {
   685     case SDL_TEXTURESCALEMODE_NONE:
   686     case SDL_TEXTURESCALEMODE_FAST:
   687         data->render_options = DSRO_NONE;
   688         break;
   689     case SDL_TEXTURESCALEMODE_SLOW:
   690         data->render_options = DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE;
   691         break;
   692     case SDL_TEXTURESCALEMODE_BEST:
   693         data->render_options =
   694             DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE | DSRO_ANTIALIAS;
   695         break;
   696     default:
   697         SDL_Unsupported();
   698         data->render_options = DSRO_NONE;
   699         texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
   700         return -1;
   701     }
   702 #endif
   703     return 0;
   704 }
   705 
   706 static int
   707 DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   708                        const SDL_Rect * rect, const void *pixels, int pitch)
   709 {
   710     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   711     DFBResult ret;
   712     Uint8 *dpixels;
   713     int dpitch;
   714     Uint8 *src, *dst;
   715     int row;
   716     size_t length;
   717     int bpp = DFB_BYTES_PER_PIXEL(SDLToDFBPixelFormat(texture->format));
   718     // FIXME: SDL_BYTESPERPIXEL(texture->format) broken for yuv yv12 3 planes
   719 
   720     SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
   721                                          DSLF_WRITE | DSLF_READ,
   722                                          ((void **) &dpixels), &dpitch));
   723     src = (Uint8 *) pixels;
   724     dst = (Uint8 *) dpixels + rect->y * dpitch + rect->x * bpp;
   725     length = rect->w * bpp;
   726     for (row = 0; row < rect->h; ++row) {
   727         SDL_memcpy(dst, src, length);
   728         src += pitch;
   729         dst += dpitch;
   730     }
   731     SDL_DFB_CHECKERR(data->surface->Unlock(data->surface));
   732     return 0;
   733   error:
   734     return 1;
   735 
   736 }
   737 
   738 static int
   739 DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   740                      const SDL_Rect * rect, int markDirty, void **pixels,
   741                      int *pitch)
   742 {
   743     DirectFB_TextureData *texturedata =
   744         (DirectFB_TextureData *) texture->driverdata;
   745     DFBResult ret;
   746 
   747     if (markDirty) {
   748         SDL_AddDirtyRect(&texturedata->dirty, rect);
   749     }
   750 
   751     if (texturedata->display) {
   752         void *fdata;
   753         int fpitch;
   754 
   755         SDL_DFB_CHECKERR(texturedata->surface->Lock(texturedata->surface,
   756                                                     DSLF_WRITE | DSLF_READ,
   757                                                     &fdata, &fpitch));
   758         *pitch = fpitch;
   759         *pixels = fdata;
   760     } else {
   761         *pixels =
   762             (void *) ((Uint8 *) texturedata->pixels +
   763                       rect->y * texturedata->pitch +
   764                       rect->x * SDL_BYTESPERPIXEL(texture->format));
   765         *pitch = texturedata->pitch;
   766     }
   767     return 0;
   768 
   769   error:
   770     return -1;
   771 }
   772 
   773 static void
   774 DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   775 {
   776     DirectFB_TextureData *texturedata =
   777         (DirectFB_TextureData *) texture->driverdata;
   778 
   779     if (texturedata->display) {
   780         texturedata->surface->Unlock(texturedata->surface);
   781         texturedata->pixels = NULL;
   782     }
   783 }
   784 
   785 static void
   786 DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   787                       int numrects, const SDL_Rect * rects)
   788 {
   789     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   790     int i;
   791 
   792     for (i = 0; i < numrects; ++i) {
   793         SDL_AddDirtyRect(&data->dirty, &rects[i]);
   794     }
   795 }
   796 
   797 static int
   798 PrepareDraw(SDL_Renderer * renderer)
   799 {
   800     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   801     DFBResult ret;
   802     Uint8 r, g, b, a;
   803 
   804     r = renderer->r;
   805     g = renderer->g;
   806     b = renderer->b;
   807     a = renderer->a;
   808 
   809     SetBlendMode(data, renderer->blendMode, NULL);
   810     SDL_DFB_CHECKERR(data->surface->
   811                      SetDrawingFlags(data->surface, data->drawFlags));
   812 
   813     switch (renderer->blendMode) {
   814     case SDL_BLENDMODE_NONE:
   815     case SDL_BLENDMODE_MASK:
   816     case SDL_BLENDMODE_BLEND:
   817         break;
   818     case SDL_BLENDMODE_ADD:
   819     case SDL_BLENDMODE_MOD:
   820         r = ((int) r * (int) a) / 255;
   821         g = ((int) g * (int) a) / 255;
   822         b = ((int) b * (int) a) / 255;
   823         a = 255;
   824         break;
   825     }
   826 
   827     SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, r, g, b, a));
   828     return 0;
   829   error:
   830     return -1;
   831 }
   832 
   833 static int
   834 DirectFB_RenderPoint(SDL_Renderer * renderer, int x, int y)
   835 {
   836     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   837     DFBResult ret;
   838 
   839     PrepareDraw(renderer);
   840     SDL_DFB_CHECKERR(data->surface->DrawLine(data->surface, x, y, x, y));
   841     return 0;
   842   error:
   843     return -1;
   844 }
   845 
   846 static int
   847 DirectFB_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
   848 {
   849     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   850     DFBResult ret;
   851 
   852     PrepareDraw(renderer);
   853     /* Use antialiasing when available */
   854 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   855     SDL_DFB_CHECKERR(data->surface->SetRenderOptions(data->surface,
   856                                                      DSRO_ANTIALIAS));
   857 #endif
   858     SDL_DFB_CHECKERR(data->surface->DrawLine(data->surface, x1, y1, x2, y2));
   859     return 0;
   860   error:
   861     return -1;
   862 }
   863 
   864 static int
   865 DirectFB_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
   866 {
   867     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   868     DFBResult ret;
   869 
   870     PrepareDraw(renderer);
   871     SDL_DFB_CHECKERR(data->surface->
   872                      FillRectangle(data->surface, rect->x, rect->y, rect->w,
   873                                    rect->h));
   874 
   875     return 0;
   876   error:
   877     return -1;
   878 }
   879 
   880 static int
   881 DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   882                     const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   883 {
   884     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   885     DirectFB_TextureData *texturedata =
   886         (DirectFB_TextureData *) texture->driverdata;
   887     Uint8 alpha = 0xFF;
   888     DFBResult ret;
   889 
   890     if (texturedata->display) {
   891         int px, py;
   892         SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   893         SDL_DFB_WINDOWDATA(window);
   894         SDL_VideoDisplay *display = texturedata->display;
   895         DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   896 
   897         SDL_DFB_CHECKERR(dispdata->vidlayer->
   898                          SetSourceRectangle(dispdata->vidlayer, srcrect->x,
   899                                             srcrect->y, srcrect->w,
   900                                             srcrect->h));
   901         windata->window->GetPosition(windata->window, &px, &py);
   902         SDL_DFB_CHECKERR(dispdata->vidlayer->
   903                          SetScreenRectangle(dispdata->vidlayer,
   904                                             px + dstrect->x, py + dstrect->y,
   905                                             dstrect->w, dstrect->h));
   906     } else {
   907         DFBRectangle sr, dr;
   908         DFBSurfaceBlittingFlags flags = 0;
   909 
   910         if (texturedata->dirty.list) {
   911             SDL_DirtyRect *dirty;
   912             void *pixels;
   913             int bpp = SDL_BYTESPERPIXEL(texture->format);
   914             int pitch = texturedata->pitch;
   915 
   916             for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   917                 SDL_Rect *rect = &dirty->rect;
   918                 pixels =
   919                     (void *) ((Uint8 *) texturedata->pixels +
   920                               rect->y * pitch + rect->x * bpp);
   921                 DirectFB_UpdateTexture(renderer, texture, rect,
   922                                        texturedata->pixels,
   923                                        texturedata->pitch);
   924             }
   925             SDL_ClearDirtyRects(&texturedata->dirty);
   926         }
   927 
   928         SDLtoDFBRect(srcrect, &sr);
   929         SDLtoDFBRect(dstrect, &dr);
   930 
   931         SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   932                                                  0xFF, 0xFF, 0xFF));
   933         if (texture->
   934             modMode & (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA))
   935         {
   936             if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
   937                 alpha = texture->a;
   938                 SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   939                                                          0xFF, 0xFF, alpha));
   940             }
   941             if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
   942 
   943                 SDL_DFB_CHECKERR(data->surface->
   944                                  SetColor(data->surface, texture->r,
   945                                           texture->g, texture->b, alpha));
   946                 flags |= DSBLIT_COLORIZE;
   947             }
   948             if (alpha < 0xFF)
   949                 flags |= DSBLIT_SRC_PREMULTCOLOR;
   950         } else
   951             SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   952                                                      0xFF, 0xFF, 0xFF));
   953 
   954         SetBlendMode(data, texture->blendMode, texturedata);
   955 
   956         SDL_DFB_CHECKERR(data->surface->
   957                          SetBlittingFlags(data->surface,
   958                                           data->blitFlags | flags));
   959 
   960 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   961         SDL_DFB_CHECKERR(data->surface->SetRenderOptions(data->surface,
   962                                                          texturedata->
   963                                                          render_options));
   964 #endif
   965 
   966         if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
   967             SDL_DFB_CHECKERR(data->surface->
   968                              Blit(data->surface, texturedata->surface,
   969                                   &sr, dr.x, dr.y));
   970         } else {
   971             SDL_DFB_CHECKERR(data->surface->
   972                              StretchBlit(data->surface, texturedata->surface,
   973                                          &sr, &dr));
   974         }
   975     }
   976     return 0;
   977   error:
   978     return -1;
   979 }
   980 
   981 static void
   982 DirectFB_RenderPresent(SDL_Renderer * renderer)
   983 {
   984     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   985     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   986 
   987     DFBRectangle sr;
   988     DFBResult ret;
   989 
   990     sr.x = 0;
   991     sr.y = 0;
   992     sr.w = window->w;
   993     sr.h = window->h;
   994 
   995     /* Send the data to the display */
   996     SDL_DFB_CHECKERR(data->surface->
   997                      Flip(data->surface, NULL, data->flipflags));
   998 
   999     return;
  1000   error:
  1001     return;
  1002 }
  1003 
  1004 static void
  1005 DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1006 {
  1007     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
  1008 
  1009     if (!data) {
  1010         return;
  1011     }
  1012     SDL_DFB_RELEASE(data->palette);
  1013     SDL_DFB_RELEASE(data->surface);
  1014     if (data->display) {
  1015         DFB_DisplayData *dispdata =
  1016             (DFB_DisplayData *) data->display->driverdata;
  1017         dispdata->vidIDinuse = 0;
  1018         dispdata->vidlayer->SetCooperativeLevel(dispdata->vidlayer,
  1019                                                 DLSCL_ADMINISTRATIVE);
  1020         SDL_DFB_RELEASE(dispdata->vidlayer);
  1021     }
  1022     SDL_FreeDirtyRects(&data->dirty);
  1023     SDL_DFB_FREE(data->pixels);
  1024     SDL_free(data);
  1025     texture->driverdata = NULL;
  1026 }
  1027 
  1028 static void
  1029 DirectFB_DestroyRenderer(SDL_Renderer * renderer)
  1030 {
  1031     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1032 
  1033     if (data) {
  1034         SDL_DFB_RELEASE(data->surface);
  1035         SDL_free(data);
  1036     }
  1037     SDL_free(renderer);
  1038 }
  1039 
  1040 /* vi: set ts=4 sw=4 expandtab: */