src/video/directfb/SDL_DirectFB_window.c
author Sam Lantinga
Sun, 13 Feb 2011 13:46:10 -0800
changeset 5288 d4381f3b0d1e
parent 5262 b530ef003506
child 5478 6b65ff3cee62
permissions -rw-r--r--
A few fixes:
Fixed creating render texture framebuffer.
Removed the need for palette watch, added surface format caching.
Added an SDL_DONTFREE flag so you can't free the window and 1.2 shadow surfaces.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2011 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 DirectFB driver by couriersud@arcor.de
    23 	
    24 */
    25 
    26 #include "SDL_DirectFB_video.h"
    27 #include "SDL_DirectFB_modes.h"
    28 #include "SDL_DirectFB_window.h"
    29 #include "SDL_DirectFB_shape.h"
    30 
    31 #if SDL_DIRECTFB_OPENGL
    32 #include "SDL_DirectFB_opengl.h"
    33 #endif
    34 
    35 #include "SDL_syswm.h"
    36 
    37 #include "../SDL_pixels_c.h"
    38 
    39 int
    40 DirectFB_CreateWindow(_THIS, SDL_Window * window)
    41 {
    42     SDL_DFB_DEVICEDATA(_this);
    43     SDL_DFB_DISPLAYDATA(window);
    44     DFB_WindowData *windata = NULL;
    45     DFBWindowOptions wopts;
    46     DFBWindowDescription desc;
    47     int x, y;
    48     int bshaped = 0;
    49 
    50     SDL_DFB_ALLOC_CLEAR(window->driverdata, sizeof(DFB_WindowData));
    51     windata = (DFB_WindowData *) window->driverdata;
    52 
    53     windata->is_managed = devdata->has_own_wm;
    54 #if 1
    55     SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
    56                                                        DFSCL_NORMAL));
    57     SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
    58                                                           DLSCL_ADMINISTRATIVE));
    59 #endif
    60 	/* FIXME ... ughh, ugly */
    61 	if (window->x == -1000 && window->y == -1000)
    62 		bshaped = 1;
    63 	
    64     /* Fill the window description. */
    65     if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
    66         x = (dispdata->cw - window->w) / 2;
    67     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->x)) {
    68         x = 0;
    69     } else {
    70         x = window->x;
    71     }
    72     
    73     if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
    74         y = (dispdata->ch - window->h) / 2;
    75     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->y)) {
    76         y = 0;
    77     } else {
    78         y = window->y;
    79     }
    80     
    81     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    82         x = 0;
    83         y = 0;
    84     }
    85 
    86     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
    87 
    88     /* Create Window */
    89 	desc.caps = 0;
    90     desc.flags =
    91         DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    92 
    93     if (bshaped) {
    94     	desc.flags |= DWDESC_CAPS;
    95     	desc.caps |= DWCAPS_ALPHACHANNEL;
    96     }
    97     else
    98     {
    99     	desc.flags |= DWDESC_PIXELFORMAT;
   100     }
   101 
   102     if (!(window->flags & SDL_WINDOW_BORDERLESS))
   103 		desc.caps |= DWCAPS_NODECORATION;
   104 
   105     desc.posx = x;
   106     desc.posy = y;
   107     desc.width = windata->size.w;
   108     desc.height = windata->size.h;
   109     desc.pixelformat = dispdata->pixelformat;
   110     desc.surface_caps = DSCAPS_PREMULTIPLIED;
   111     
   112     /* Create the window. */
   113     SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
   114                                                    &windata->dfbwin));
   115 
   116     /* Set Options */
   117     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   118 
   119     /* explicit rescaling of surface */
   120     wopts |= DWOP_SCALE;
   121     if (window->flags & SDL_WINDOW_RESIZABLE) {
   122         wopts &= ~DWOP_KEEP_SIZE;
   123     }
   124     else {
   125         wopts |= DWOP_KEEP_SIZE;
   126     }
   127 
   128     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   129         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
   130         SDL_DFB_CHECK(windata->dfbwin->SetStackingClass(windata->dfbwin, DWSC_UPPER));
   131     }
   132     
   133     if (bshaped) {
   134         wopts |= DWOP_SHAPED | DWOP_ALPHACHANNEL;
   135         wopts &= ~DWOP_OPAQUE_REGION;
   136     }
   137 
   138     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   139 
   140     /* See what we got */
   141     SDL_DFB_CHECK(DirectFB_WM_GetClientSize
   142                      (_this, window, &window->w, &window->h));
   143 
   144     /* Get the window's surface. */
   145     SDL_DFB_CHECKERR(windata->dfbwin->GetSurface(windata->dfbwin,
   146                                                  &windata->window_surface));
   147 
   148     /* And get a subsurface for rendering */
   149     SDL_DFB_CHECKERR(windata->window_surface->
   150                      GetSubSurface(windata->window_surface, &windata->client,
   151                                    &windata->surface));
   152 
   153     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0xFF));
   154 
   155     /* Create Eventbuffer */
   156 
   157     SDL_DFB_CHECKERR(windata->dfbwin->CreateEventBuffer(windata->dfbwin,
   158                                                         &windata->
   159                                                         eventbuffer));
   160     SDL_DFB_CHECKERR(windata->dfbwin->
   161                      EnableEvents(windata->dfbwin, DWET_ALL));
   162 
   163     /* Create a font */
   164     /* FIXME: once during Video_Init */
   165     windata->font = NULL;
   166 
   167     /* Make it the top most window. */
   168     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   169 
   170     /* remember parent */
   171     //windata->sdlwin = window;
   172 
   173     /* Add to list ... */
   174 
   175     windata->next = devdata->firstwin;
   176     windata->opacity = 0xFF;
   177     devdata->firstwin = window;
   178 
   179     /* Draw Frame */
   180     DirectFB_WM_RedrawLayout(_this, window);
   181 
   182     return 0;
   183   error:
   184 	SDL_DFB_RELEASE(windata->surface);
   185     SDL_DFB_RELEASE(windata->dfbwin);
   186     return -1;
   187 }
   188 
   189 int
   190 DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   191 {
   192     SDL_Unsupported();
   193     return -1;
   194 }
   195 
   196 void
   197 DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
   198 {
   199     SDL_DFB_WINDOWDATA(window);
   200 
   201     if (windata->is_managed) {
   202         windata->wm_needs_redraw = 1;
   203         DirectFB_WM_RedrawLayout(_this, window);
   204     } else
   205         SDL_Unsupported();
   206 }
   207 
   208 void
   209 DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   210 {
   211     SDL_DFB_DEVICEDATA(_this);
   212     SDL_DFB_WINDOWDATA(window);
   213     SDL_Surface *surface = NULL;
   214 
   215     if (icon) {
   216         SDL_PixelFormat format;
   217         DFBSurfaceDescription dsc;
   218         Uint32 *dest;
   219         Uint32 *p;
   220         int pitch, i;
   221 
   222         /* Convert the icon to ARGB for modern window managers */
   223         SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
   224         surface = SDL_ConvertSurface(icon, &format, 0);
   225         if (!surface) {
   226             return;
   227         }
   228         dsc.flags =
   229             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   230         dsc.caps = DSCAPS_VIDEOONLY;
   231         dsc.width = surface->w;
   232         dsc.height = surface->h;
   233         dsc.pixelformat = DSPF_ARGB;
   234 
   235         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   236                                                      &windata->icon));
   237 
   238         SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
   239                                              (void *) &dest, &pitch));
   240 
   241         p = surface->pixels;
   242         for (i = 0; i < surface->h; i++)
   243             memcpy((char *) dest + i * pitch,
   244                    (char *) p + i * surface->pitch, 4 * surface->w);
   245 
   246         SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
   247         SDL_FreeSurface(surface);
   248     } else {
   249         SDL_DFB_RELEASE(windata->icon);
   250     }
   251     return;
   252   error:
   253     if (surface)
   254         SDL_FreeSurface(surface);
   255     SDL_DFB_RELEASE(windata->icon);
   256     return;
   257 }
   258 
   259 void
   260 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   261 {
   262     SDL_DFB_WINDOWDATA(window);
   263     SDL_DFB_DISPLAYDATA(window);
   264     int x, y;
   265 
   266     if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
   267         x = (dispdata->cw - window->w) / 2;
   268     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->x)) {
   269         x = 0;
   270     } else {
   271         x = window->x;
   272     }
   273     
   274     if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
   275         y = (dispdata->ch - window->h) / 2;
   276     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->y)) {
   277         y = 0;
   278     } else {
   279         y = window->y;
   280     }
   281 
   282     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   283         x = 0;
   284         y = 0;
   285     }
   286     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   287     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, x, y));
   288 }
   289 
   290 void
   291 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   292 {
   293     SDL_DFB_WINDOWDATA(window);
   294 
   295     if(SDL_IsShapedWindow(window))
   296         DirectFB_ResizeWindowShape(window);
   297 
   298     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   299         int cw;
   300         int ch;
   301 
   302         /* Make sure all events are disabled for this operation ! */
   303         SDL_DFB_CHECKERR(windata->dfbwin->DisableEvents(windata->dfbwin,
   304                                                         DWET_ALL));
   305         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   306 
   307         if (cw != window->w || ch != window->h) {
   308 
   309 		    DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   310             SDL_DFB_CHECKERR(windata->dfbwin->Resize(windata->dfbwin,
   311                                                      windata->size.w,
   312                                                      windata->size.h));
   313         }
   314 
   315         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   316                      (_this, window, &window->w, &window->h));
   317         DirectFB_AdjustWindowSurface(window);
   318 
   319         SDL_DFB_CHECKERR(windata->dfbwin->EnableEvents(windata->dfbwin,
   320                                                        DWET_ALL));
   321 
   322     }
   323     return;
   324   error:
   325     SDL_DFB_CHECK(windata->dfbwin->EnableEvents(windata->dfbwin, DWET_ALL));
   326     return;
   327 }
   328 
   329 void
   330 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   331 {
   332     SDL_DFB_WINDOWDATA(window);
   333 
   334     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, windata->opacity));
   335 
   336 }
   337 
   338 void
   339 DirectFB_HideWindow(_THIS, SDL_Window * window)
   340 {
   341     SDL_DFB_WINDOWDATA(window);
   342 
   343     SDL_DFB_CHECK(windata->dfbwin->GetOpacity(windata->dfbwin, &windata->opacity));
   344     SDL_DFB_CHECK(windata->dfbwin->SetOpacity(windata->dfbwin, 0));
   345 }
   346 
   347 void
   348 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   349 {
   350     SDL_DFB_WINDOWDATA(window);
   351 
   352     SDL_DFB_CHECK(windata->dfbwin->RaiseToTop(windata->dfbwin));
   353     SDL_DFB_CHECK(windata->dfbwin->RequestFocus(windata->dfbwin));
   354 }
   355 
   356 void
   357 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   358 {
   359     SDL_DFB_WINDOWDATA(window);
   360     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   361     DFBWindowOptions wopts;
   362 
   363     SDL_DFB_CHECK(windata->dfbwin->GetPosition(windata->dfbwin,
   364                                  &windata->restore.x, &windata->restore.y));
   365     SDL_DFB_CHECK(windata->dfbwin->GetSize(windata->dfbwin, &windata->restore.w,
   366                              &windata->restore.h));
   367 
   368     DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
   369 
   370     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, 0, 0));
   371     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin,
   372                             display->current_mode.w, display->current_mode.h));
   373 
   374     /* Set Options */
   375     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   376     wopts |= DWOP_KEEP_SIZE | DWOP_KEEP_POSITION;
   377     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   378 }
   379 
   380 void
   381 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   382 {
   383     /* FIXME: Size to 32x32 ? */
   384 
   385     SDL_Unsupported();
   386 }
   387 
   388 void
   389 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   390 {
   391     SDL_DFB_WINDOWDATA(window);
   392     DFBWindowOptions wopts;
   393 
   394     /* Set Options */
   395     SDL_DFB_CHECK(windata->dfbwin->GetOptions(windata->dfbwin, &wopts));
   396     wopts &= ~(DWOP_KEEP_SIZE | DWOP_KEEP_POSITION);
   397     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   398 
   399     /* Window layout */
   400     DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
   401     	windata->restore.w, windata->restore.h);
   402     SDL_DFB_CHECK(windata->dfbwin->Resize(windata->dfbwin, windata->restore.w,
   403                             windata->restore.h));
   404     SDL_DFB_CHECK(windata->dfbwin->MoveTo(windata->dfbwin, windata->restore.x,
   405                             windata->restore.y));
   406 
   407     if (!(window->flags & SDL_WINDOW_RESIZABLE))
   408         wopts |= DWOP_KEEP_SIZE;
   409 
   410     if (window->flags & SDL_WINDOW_FULLSCREEN)
   411         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_SIZE;
   412     SDL_DFB_CHECK(windata->dfbwin->SetOptions(windata->dfbwin, wopts));
   413 
   414 
   415 }
   416 
   417 void
   418 DirectFB_SetWindowGrab(_THIS, SDL_Window * window)
   419 {
   420     SDL_DFB_DEVICEDATA(_this);
   421     SDL_DFB_WINDOWDATA(window);
   422     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   423 
   424     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   425         if (gwindata != NULL)
   426         {
   427 		    SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
   428 		    SDL_DFB_CHECK(gwindata->dfbwin->UngrabKeyboard(gwindata->dfbwin));
   429         }
   430         SDL_DFB_CHECK(windata->dfbwin->GrabPointer(windata->dfbwin));
   431         SDL_DFB_CHECK(windata->dfbwin->GrabKeyboard(windata->dfbwin));
   432         devdata->grabbed_window = window;
   433     } else {
   434         SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   435         SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   436         devdata->grabbed_window = NULL;
   437     }
   438 }
   439 
   440 void
   441 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   442 {
   443     SDL_DFB_DEVICEDATA(_this);
   444     SDL_DFB_WINDOWDATA(window);
   445     DFB_WindowData *p;
   446 
   447     /* Some cleanups */
   448     SDL_DFB_CHECK(windata->dfbwin->UngrabPointer(windata->dfbwin));
   449     SDL_DFB_CHECK(windata->dfbwin->UngrabKeyboard(windata->dfbwin));
   450 
   451 #if SDL_DIRECTFB_OPENGL
   452 	DirectFB_GL_DestroyWindowContexts(_this, window);
   453 #endif
   454 
   455 	if (window->shaper)
   456 	{
   457 	    SDL_ShapeData *data = window->shaper->driverdata;
   458 	    SDL_DFB_CHECK(data->surface->ReleaseSource(data->surface));
   459     	SDL_DFB_RELEASE(data->surface);
   460     	SDL_DFB_FREE(data);
   461     	SDL_DFB_FREE(window->shaper);
   462 	}
   463 
   464     SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
   465     SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
   466     SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
   467   	SDL_DFB_RELEASE(windata->icon);
   468     SDL_DFB_RELEASE(windata->font);
   469     SDL_DFB_RELEASE(windata->eventbuffer);
   470     SDL_DFB_RELEASE(windata->surface);
   471     SDL_DFB_RELEASE(windata->window_surface);
   472 
   473     SDL_DFB_RELEASE(windata->dfbwin);
   474 
   475     /* Remove from list ... */
   476 
   477     p = devdata->firstwin->driverdata;
   478 
   479     while (p && p->next != window)
   480         p = (p->next ? p->next->driverdata : NULL);
   481     if (p)
   482         p->next = windata->next;
   483     else
   484         devdata->firstwin = windata->next;
   485     SDL_free(windata);
   486     return;
   487 }
   488 
   489 SDL_bool
   490 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   491                          struct SDL_SysWMinfo * info)
   492 {
   493     SDL_DFB_DEVICEDATA(_this);
   494     SDL_DFB_WINDOWDATA(window);
   495 
   496     if (info->version.major == SDL_MAJOR_VERSION &&
   497         info->version.minor == SDL_MINOR_VERSION) {
   498         info->subsystem = SDL_SYSWM_DIRECTFB;
   499         info->info.dfb.dfb = devdata->dfb;
   500         info->info.dfb.window = windata->dfbwin;
   501         info->info.dfb.surface = windata->surface;
   502         return SDL_TRUE;
   503     } else {
   504         SDL_SetError("Application not compiled with SDL %d.%d\n",
   505                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   506         return SDL_FALSE;
   507     }
   508 }
   509 
   510 void
   511 DirectFB_AdjustWindowSurface(SDL_Window * window)
   512 {
   513     SDL_DFB_WINDOWDATA(window);
   514     int adjust = windata->wm_needs_redraw;
   515     int cw, ch;
   516 
   517     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   518 
   519     SDL_DFB_CHECKERR(windata->
   520                      window_surface->GetSize(windata->window_surface, &cw,
   521                                              &ch));
   522     if (cw != windata->size.w || ch != windata->size.h) {
   523         adjust = 1;
   524     }
   525 
   526     if (adjust) {
   527 #if SDL_DIRECTFB_OPENGL
   528 		DirectFB_GL_FreeWindowContexts(SDL_GetVideoDevice(), window);
   529 #endif
   530 
   531 #if (DFB_VERSION_ATLEAST(1,2,1))
   532         SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   533                                                         windata->size.w,
   534                                                         windata->size.h));
   535         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   536                                                           windata->
   537                                                           window_surface,
   538                                                           &windata->client));
   539 #else
   540         DFBWindowOptions opts;
   541 
   542         SDL_DFB_CHECKERR(windata->dfbwin->GetOptions(windata->dfbwin, &opts));
   543         /* recreate subsurface */
   544         SDL_DFB_RELEASE(windata->surface);
   545 
   546         if (opts & DWOP_SCALE)
   547             SDL_DFB_CHECKERR(windata->dfbwin->ResizeSurface(windata->dfbwin,
   548                                                             windata->size.w,
   549                                                             windata->size.h));
   550         SDL_DFB_CHECKERR(windata->window_surface->
   551                          GetSubSurface(windata->window_surface,
   552                                        &windata->client, &windata->surface));
   553 #endif
   554         DirectFB_WM_RedrawLayout(SDL_GetVideoDevice(), window);
   555         
   556 #if SDL_DIRECTFB_OPENGL
   557 		DirectFB_GL_ReAllocWindowContexts(SDL_GetVideoDevice(), window);
   558 #endif
   559    }
   560   error:
   561     return;
   562 }