src/video/directfb/SDL_DirectFB_render.c
author Bob Pendleton <bob@pendleton.com>
Fri, 09 Jan 2009 20:43:30 +0000
changeset 3011 8f4ed5ec2b06
parent 2930 8acbb14124c5
child 3013 8cc00819c8d6
permissions -rw-r--r--
I ran a global "make indent" it modified the following files.
     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->
   422                          surface->GetSize(windata->surface, &cw, &ch));
   423         if (cw != window->w || ch != window->h)
   424             SDL_DFB_CHECKERR(windata->
   425                              window->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->
   466                          dfb->GetDisplayLayer(devdata->dfb, dispdata->vidID,
   467                                               &dispdata->vidlayer));
   468         SDL_DFB_CHECKERR(dispdata->
   469                          vidlayer->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->
   478                          vidlayer->SetConfiguration(dispdata->vidlayer,
   479                                                     &layconf));
   480         SDL_DFB_CHECKERR(dispdata->
   481                          vidlayer->GetSurface(dispdata->vidlayer,
   482                                               &data->surface));
   483         dispdata->vidIDinuse = 1;
   484         data->display = display;
   485         return 0;
   486     }
   487     return 1;
   488   error:
   489     if (dispdata->vidlayer) {
   490         SDL_DFB_RELEASE(data->surface);
   491         SDL_DFB_CHECKERR(dispdata->
   492                          vidlayer->SetCooperativeLevel(dispdata->vidlayer,
   493                                                        DLSCL_ADMINISTRATIVE));
   494         SDL_DFB_RELEASE(dispdata->vidlayer);
   495     }
   496     return 1;
   497 }
   498 
   499 static int
   500 DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   501 {
   502     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   503     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   504     SDL_DFB_DEVICEDATA(display->device);
   505     DirectFB_TextureData *data;
   506     DFBResult ret;
   507     DFBSurfaceDescription dsc;
   508 
   509     SDL_DFB_CALLOC(data, 1, sizeof(*data));
   510     texture->driverdata = data;
   511 
   512     data->format = texture->format;
   513     data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
   514 
   515     if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
   516         /* fill surface description */
   517         dsc.flags =
   518             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   519         dsc.width = texture->w;
   520         dsc.height = texture->h;
   521         /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
   522          * No DSCAPS_SYSTEMONLY either - let dfb decide
   523          * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
   524          * Depends on other settings as well. Let dfb decide.
   525          */
   526         dsc.caps = DSCAPS_PREMULTIPLIED;
   527 #if 0
   528         if (texture->access == SDL_TEXTUREACCESS_STREAMING)
   529             dsc.caps |= DSCAPS_SYSTEMONLY;
   530         else
   531             dsc.caps |= DSCAPS_VIDEOONLY;
   532 #endif
   533 
   534         /* find the right pixelformat */
   535 
   536         dsc.pixelformat = SDLToDFBPixelFormat(data->format);
   537         if (dsc.pixelformat == DSPF_UNKNOWN) {
   538             SDL_SetError("Unknown pixel format %d\n", data->format);
   539             goto error;
   540         }
   541 
   542         data->pixels = NULL;
   543 
   544         /* Create the surface */
   545         SDL_DFB_CHECKERR(devdata->
   546                          dfb->CreateSurface(devdata->dfb, &dsc,
   547                                             &data->surface));
   548         if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   549             && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   550             SDL_DFB_CHECKERR(data->
   551                              surface->GetPalette(data->surface,
   552                                                  &data->palette));
   553         }
   554 
   555     }
   556 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   557     data->render_options = DSRO_NONE;
   558 #endif
   559 
   560     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   561         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   562         SDL_DFB_CALLOC(data->pixels, 1, texture->h * data->pitch);
   563     }
   564 
   565     return 0;
   566 
   567   error:
   568     SDL_DFB_RELEASE(data->palette);
   569     SDL_DFB_RELEASE(data->surface);
   570     SDL_DFB_FREE(texture->driverdata);
   571     return -1;
   572 }
   573 
   574 static int
   575 DirectFB_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   576                             void **pixels, int *pitch)
   577 {
   578     DirectFB_TextureData *texturedata =
   579         (DirectFB_TextureData *) texture->driverdata;
   580 
   581     if (texturedata->display) {
   582         return -1;
   583     } else {
   584         *pixels = texturedata->pixels;
   585         *pitch = texturedata->pitch;
   586     }
   587     return 0;
   588 }
   589 
   590 static int
   591 DirectFB_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   592                            const SDL_Color * colors, int firstcolor,
   593                            int ncolors)
   594 {
   595     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   596     DFBResult ret;
   597 
   598     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   599         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   600         DFBColor entries[256];
   601         int i;
   602 
   603         for (i = 0; i < ncolors; ++i) {
   604             entries[i].r = colors[i].r;
   605             entries[i].g = colors[i].g;
   606             entries[i].b = colors[i].b;
   607             entries[i].a = 0xFF;
   608         }
   609         SDL_DFB_CHECKERR(data->
   610                          palette->SetEntries(data->palette, entries, ncolors,
   611                                              firstcolor));
   612         return 0;
   613     } else {
   614         SDL_SetError("YUV textures don't have a palette");
   615         return -1;
   616     }
   617   error:
   618     return -1;
   619 }
   620 
   621 static int
   622 DirectFB_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   623                            SDL_Color * colors, int firstcolor, int ncolors)
   624 {
   625     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   626     DFBResult ret;
   627 
   628     if (SDL_ISPIXELFORMAT_INDEXED(data->format)
   629         && !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
   630         DFBColor entries[256];
   631         int i;
   632 
   633         SDL_DFB_CHECKERR(data->
   634                          palette->GetEntries(data->palette, entries, ncolors,
   635                                              firstcolor));
   636 
   637         for (i = 0; i < ncolors; ++i) {
   638             colors[i].r = entries[i].r;
   639             colors[i].g = entries[i].g;
   640             colors[i].b = entries[i].b;
   641             colors->unused = SDL_ALPHA_OPAQUE;
   642         }
   643         return 0;
   644     } else {
   645         SDL_SetError("YUV textures don't have a palette");
   646         return -1;
   647     }
   648   error:
   649     return -1;
   650 }
   651 
   652 static int
   653 DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   654 {
   655     return 0;
   656 }
   657 
   658 static int
   659 DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   660 {
   661     return 0;
   662 }
   663 
   664 static int
   665 DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   666 {
   667     switch (texture->blendMode) {
   668     case SDL_BLENDMODE_NONE:
   669     case SDL_BLENDMODE_MASK:
   670     case SDL_BLENDMODE_BLEND:
   671     case SDL_BLENDMODE_ADD:
   672     case SDL_BLENDMODE_MOD:
   673         return 0;
   674     default:
   675         SDL_Unsupported();
   676         texture->blendMode = SDL_BLENDMODE_NONE;
   677         return -1;
   678     }
   679 }
   680 
   681 static int
   682 DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   683 {
   684 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   685 
   686     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   687 
   688     switch (texture->scaleMode) {
   689     case SDL_TEXTURESCALEMODE_NONE:
   690     case SDL_TEXTURESCALEMODE_FAST:
   691         data->render_options = DSRO_NONE;
   692         break;
   693     case SDL_TEXTURESCALEMODE_SLOW:
   694         data->render_options = DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE;
   695         break;
   696     case SDL_TEXTURESCALEMODE_BEST:
   697         data->render_options =
   698             DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE | DSRO_ANTIALIAS;
   699         break;
   700     default:
   701         SDL_Unsupported();
   702         data->render_options = DSRO_NONE;
   703         texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
   704         return -1;
   705     }
   706 #endif
   707     return 0;
   708 }
   709 
   710 static int
   711 DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   712                        const SDL_Rect * rect, const void *pixels, int pitch)
   713 {
   714     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   715     DFBResult ret;
   716     Uint8 *dpixels;
   717     int dpitch;
   718     Uint8 *src, *dst;
   719     int row;
   720     size_t length;
   721     int bpp = DFB_BYTES_PER_PIXEL(SDLToDFBPixelFormat(texture->format));
   722     // FIXME: SDL_BYTESPERPIXEL(texture->format) broken for yuv yv12 3 planes
   723 
   724     SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
   725                                          DSLF_WRITE | DSLF_READ,
   726                                          ((void **) &dpixels), &dpitch));
   727     src = (Uint8 *) pixels;
   728     dst = (Uint8 *) dpixels + rect->y * dpitch + rect->x * bpp;
   729     length = rect->w * bpp;
   730     for (row = 0; row < rect->h; ++row) {
   731         SDL_memcpy(dst, src, length);
   732         src += pitch;
   733         dst += dpitch;
   734     }
   735     SDL_DFB_CHECKERR(data->surface->Unlock(data->surface));
   736     return 0;
   737   error:
   738     return 1;
   739 
   740 }
   741 
   742 static int
   743 DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   744                      const SDL_Rect * rect, int markDirty, void **pixels,
   745                      int *pitch)
   746 {
   747     DirectFB_TextureData *texturedata =
   748         (DirectFB_TextureData *) texture->driverdata;
   749     DFBResult ret;
   750 
   751     if (markDirty) {
   752         SDL_AddDirtyRect(&texturedata->dirty, rect);
   753     }
   754 
   755     if (texturedata->display) {
   756         void *fdata;
   757         int fpitch;
   758 
   759         SDL_DFB_CHECKERR(texturedata->surface->Lock(texturedata->surface,
   760                                                     DSLF_WRITE | DSLF_READ,
   761                                                     &fdata, &fpitch));
   762         *pitch = fpitch;
   763         *pixels = fdata;
   764     } else {
   765         *pixels =
   766             (void *) ((Uint8 *) texturedata->pixels +
   767                       rect->y * texturedata->pitch +
   768                       rect->x * SDL_BYTESPERPIXEL(texture->format));
   769         *pitch = texturedata->pitch;
   770     }
   771     return 0;
   772 
   773   error:
   774     return -1;
   775 }
   776 
   777 static void
   778 DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   779 {
   780     DirectFB_TextureData *texturedata =
   781         (DirectFB_TextureData *) texture->driverdata;
   782 
   783     if (texturedata->display) {
   784         texturedata->surface->Unlock(texturedata->surface);
   785         texturedata->pixels = NULL;
   786     }
   787 }
   788 
   789 static void
   790 DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   791                       int numrects, const SDL_Rect * rects)
   792 {
   793     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
   794     int i;
   795 
   796     for (i = 0; i < numrects; ++i) {
   797         SDL_AddDirtyRect(&data->dirty, &rects[i]);
   798     }
   799 }
   800 
   801 static int
   802 PrepareDraw(SDL_Renderer * renderer)
   803 {
   804     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   805     DFBResult ret;
   806     Uint8 r, g, b, a;
   807 
   808     r = renderer->r;
   809     g = renderer->g;
   810     b = renderer->b;
   811     a = renderer->a;
   812 
   813     SetBlendMode(data, renderer->blendMode, NULL);
   814     SDL_DFB_CHECKERR(data->
   815                      surface->SetDrawingFlags(data->surface,
   816                                               data->drawFlags));
   817 
   818     switch (renderer->blendMode) {
   819     case SDL_BLENDMODE_NONE:
   820     case SDL_BLENDMODE_MASK:
   821     case SDL_BLENDMODE_BLEND:
   822         break;
   823     case SDL_BLENDMODE_ADD:
   824     case SDL_BLENDMODE_MOD:
   825         r = ((int) r * (int) a) / 255;
   826         g = ((int) g * (int) a) / 255;
   827         b = ((int) b * (int) a) / 255;
   828         a = 255;
   829         break;
   830     }
   831 
   832     SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, r, g, b, a));
   833     return 0;
   834   error:
   835     return -1;
   836 }
   837 
   838 static int
   839 DirectFB_RenderPoint(SDL_Renderer * renderer, int x, int y)
   840 {
   841     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   842     DFBResult ret;
   843 
   844     PrepareDraw(renderer);
   845     SDL_DFB_CHECKERR(data->surface->DrawLine(data->surface, x, y, x, y));
   846     return 0;
   847   error:
   848     return -1;
   849 }
   850 
   851 static int
   852 DirectFB_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
   853 {
   854     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   855     DFBResult ret;
   856 
   857     PrepareDraw(renderer);
   858     /* Use antialiasing when available */
   859 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   860     SDL_DFB_CHECKERR(data->surface->SetRenderOptions(data->surface,
   861                                                      DSRO_ANTIALIAS));
   862 #endif
   863     SDL_DFB_CHECKERR(data->surface->DrawLine(data->surface, x1, y1, x2, y2));
   864     return 0;
   865   error:
   866     return -1;
   867 }
   868 
   869 static int
   870 DirectFB_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
   871 {
   872     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   873     DFBResult ret;
   874 
   875     PrepareDraw(renderer);
   876     SDL_DFB_CHECKERR(data->
   877                      surface->FillRectangle(data->surface, rect->x, rect->y,
   878                                             rect->w, rect->h));
   879 
   880     return 0;
   881   error:
   882     return -1;
   883 }
   884 
   885 static int
   886 DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   887                     const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   888 {
   889     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   890     DirectFB_TextureData *texturedata =
   891         (DirectFB_TextureData *) texture->driverdata;
   892     Uint8 alpha = 0xFF;
   893     DFBResult ret;
   894 
   895     if (texturedata->display) {
   896         int px, py;
   897         SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   898         SDL_DFB_WINDOWDATA(window);
   899         SDL_VideoDisplay *display = texturedata->display;
   900         DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
   901 
   902         SDL_DFB_CHECKERR(dispdata->
   903                          vidlayer->SetSourceRectangle(dispdata->vidlayer,
   904                                                       srcrect->x, srcrect->y,
   905                                                       srcrect->w,
   906                                                       srcrect->h));
   907         windata->window->GetPosition(windata->window, &px, &py);
   908         SDL_DFB_CHECKERR(dispdata->
   909                          vidlayer->SetScreenRectangle(dispdata->vidlayer,
   910                                                       px + dstrect->x,
   911                                                       py + dstrect->y,
   912                                                       dstrect->w,
   913                                                       dstrect->h));
   914     } else {
   915         DFBRectangle sr, dr;
   916         DFBSurfaceBlittingFlags flags = 0;
   917 
   918         if (texturedata->dirty.list) {
   919             SDL_DirtyRect *dirty;
   920             void *pixels;
   921             int bpp = SDL_BYTESPERPIXEL(texture->format);
   922             int pitch = texturedata->pitch;
   923 
   924             for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   925                 SDL_Rect *rect = &dirty->rect;
   926                 pixels =
   927                     (void *) ((Uint8 *) texturedata->pixels +
   928                               rect->y * pitch + rect->x * bpp);
   929                 DirectFB_UpdateTexture(renderer, texture, rect,
   930                                        texturedata->pixels,
   931                                        texturedata->pitch);
   932             }
   933             SDL_ClearDirtyRects(&texturedata->dirty);
   934         }
   935 
   936         SDLtoDFBRect(srcrect, &sr);
   937         SDLtoDFBRect(dstrect, &dr);
   938 
   939         SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   940                                                  0xFF, 0xFF, 0xFF));
   941         if (texture->modMode &
   942             (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA)) {
   943             if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
   944                 alpha = texture->a;
   945                 SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   946                                                          0xFF, 0xFF, alpha));
   947             }
   948             if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
   949 
   950                 SDL_DFB_CHECKERR(data->
   951                                  surface->SetColor(data->surface, texture->r,
   952                                                    texture->g, texture->b,
   953                                                    alpha));
   954                 flags |= DSBLIT_COLORIZE;
   955             }
   956             if (alpha < 0xFF)
   957                 flags |= DSBLIT_SRC_PREMULTCOLOR;
   958         } else
   959             SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
   960                                                      0xFF, 0xFF, 0xFF));
   961 
   962         SetBlendMode(data, texture->blendMode, texturedata);
   963 
   964         SDL_DFB_CHECKERR(data->surface->SetBlittingFlags(data->surface,
   965                                                          data->
   966                                                          blitFlags | flags));
   967 
   968 #if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 2)
   969         SDL_DFB_CHECKERR(data->surface->SetRenderOptions(data->surface,
   970                                                          texturedata->render_options));
   971 #endif
   972 
   973         if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
   974             SDL_DFB_CHECKERR(data->
   975                              surface->Blit(data->surface,
   976                                            texturedata->surface, &sr, dr.x,
   977                                            dr.y));
   978         } else {
   979             SDL_DFB_CHECKERR(data->
   980                              surface->StretchBlit(data->surface,
   981                                                   texturedata->surface, &sr,
   982                                                   &dr));
   983         }
   984     }
   985     return 0;
   986   error:
   987     return -1;
   988 }
   989 
   990 static void
   991 DirectFB_RenderPresent(SDL_Renderer * renderer)
   992 {
   993     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
   994     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   995 
   996     DFBRectangle sr;
   997     DFBResult ret;
   998 
   999     sr.x = 0;
  1000     sr.y = 0;
  1001     sr.w = window->w;
  1002     sr.h = window->h;
  1003 
  1004     /* Send the data to the display */
  1005     SDL_DFB_CHECKERR(data->
  1006                      surface->Flip(data->surface, NULL, data->flipflags));
  1007 
  1008     return;
  1009   error:
  1010     return;
  1011 }
  1012 
  1013 static void
  1014 DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1015 {
  1016     DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
  1017 
  1018     if (!data) {
  1019         return;
  1020     }
  1021     SDL_DFB_RELEASE(data->palette);
  1022     SDL_DFB_RELEASE(data->surface);
  1023     if (data->display) {
  1024         DFB_DisplayData *dispdata =
  1025             (DFB_DisplayData *) data->display->driverdata;
  1026         dispdata->vidIDinuse = 0;
  1027         dispdata->vidlayer->SetCooperativeLevel(dispdata->vidlayer,
  1028                                                 DLSCL_ADMINISTRATIVE);
  1029         SDL_DFB_RELEASE(dispdata->vidlayer);
  1030     }
  1031     SDL_FreeDirtyRects(&data->dirty);
  1032     SDL_DFB_FREE(data->pixels);
  1033     SDL_free(data);
  1034     texture->driverdata = NULL;
  1035 }
  1036 
  1037 static void
  1038 DirectFB_DestroyRenderer(SDL_Renderer * renderer)
  1039 {
  1040     DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
  1041 
  1042     if (data) {
  1043         SDL_DFB_RELEASE(data->surface);
  1044         SDL_free(data);
  1045     }
  1046     SDL_free(renderer);
  1047 }
  1048 
  1049 /* vi: set ts=4 sw=4 expandtab: */