src/video/directfb/SDL_DirectFB_window.c
author Sam Lantinga
Mon, 16 Aug 2010 09:04:55 -0700
changeset 4636 b196d2758026
parent 4568 25b9cd8bdc30
child 5199 164f20ba08eb
permissions -rw-r--r--
Couriersud to Sam

Hi Sam,

20100815_1.diff contains updates for the directfb driver:

- more documentation, mainly on software OpenGL in README.directfb
- Revised error handling leading to leaner code
- Improved/fixed OpenGL handling of multiple contexts.
- Made the built-in simple window manager handle OpenGL windows.
- Rewrote pixelformat mapping - this was quite ugly before.

Well, all software GL, but working :-)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 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 #include "SDL_config.h"
    23 
    24 #include "SDL_syswm.h"
    25 #include "../SDL_sysvideo.h"
    26 #include "../../events/SDL_keyboard_c.h"
    27 #include "../../video/SDL_pixels_c.h"
    28 
    29 #include "SDL_DirectFB_video.h"
    30 #if SDL_DIRECTFB_OPENGL
    31 #include "SDL_DirectFB_opengl.h"
    32 #endif
    33 
    34 static void DirectFB_AdjustWindowSurface(_THIS, SDL_Window * window);
    35 
    36 int
    37 DirectFB_CreateWindow(_THIS, SDL_Window * window)
    38 {
    39     SDL_DFB_DEVICEDATA(_this);
    40     SDL_DFB_DISPLAYDATA(_this, window);
    41     DFB_WindowData *windata = NULL;
    42     DFBWindowOptions wopts;
    43     DFBWindowDescription desc;
    44     int x, y;
    45 
    46     SDL_DFB_CALLOC(window->driverdata, 1, sizeof(DFB_WindowData));
    47     windata = (DFB_WindowData *) window->driverdata;
    48 
    49     windata->is_managed = devdata->has_own_wm;
    50 
    51     SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
    52                                                        DFSCL_NORMAL));
    53     SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
    54                                                           DLSCL_ADMINISTRATIVE));
    55 
    56     /* Fill the window description. */
    57     if (window->x == SDL_WINDOWPOS_CENTERED) {
    58         x = (dispdata->cw - window->w) / 2;
    59     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
    60         x = 0;
    61     } else {
    62         x = window->x;
    63     }
    64     if (window->y == SDL_WINDOWPOS_CENTERED) {
    65         y = (dispdata->ch - window->h) / 2;
    66     } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
    67         y = 0;
    68     } else {
    69         y = window->y;
    70     }
    71     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    72         x = 0;
    73         y = 0;
    74     }
    75 
    76     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
    77 
    78     /* Create Window */
    79     desc.flags =
    80         DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT | DWDESC_POSX
    81         | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    82     desc.posx = x;
    83     desc.posy = y;
    84     desc.width = windata->size.w;
    85     desc.height = windata->size.h;
    86     desc.pixelformat = dispdata->pixelformat;
    87     desc.surface_caps = DSCAPS_PREMULTIPLIED;
    88 
    89     /* Create the window. */
    90     SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
    91                                                    &windata->window));
    92 
    93     /* Set Options */
    94     SDL_DFB_CHECK(windata->window->GetOptions(windata->window, &wopts));
    95 
    96     if (window->flags & SDL_WINDOW_RESIZABLE)
    97         wopts |= DWOP_SCALE;
    98     else
    99         wopts |= DWOP_KEEP_SIZE;
   100 
   101     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   102         wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
   103         SDL_DFB_CHECK(windata->window->SetStackingClass(windata->window, DWSC_UPPER));
   104     }
   105     SDL_DFB_CHECK(windata->window->SetOptions(windata->window, wopts));
   106 
   107     /* See what we got */
   108     SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   109                      (_this, window, &window->w, &window->h));
   110 
   111     /* Get the window's surface. */
   112     SDL_DFB_CHECKERR(windata->window->GetSurface(windata->window,
   113                                                  &windata->window_surface));
   114     /* And get a subsurface for rendering */
   115     SDL_DFB_CHECKERR(windata->window_surface->
   116                      GetSubSurface(windata->window_surface, &windata->client,
   117                                    &windata->surface));
   118 
   119     SDL_DFB_CHECK(windata->window->SetOpacity(windata->window, 0xFF));
   120 
   121     /* Create Eventbuffer */
   122     SDL_DFB_CHECKERR(windata->window->CreateEventBuffer(windata->window,
   123                                                         &windata->
   124                                                         eventbuffer));
   125     SDL_DFB_CHECKERR(windata->window->
   126                      EnableEvents(windata->window, DWET_ALL));
   127 
   128     /* Create a font */
   129     /* FIXME: once during Video_Init */
   130     windata->font = NULL;
   131 
   132     /* Make it the top most window. */
   133     SDL_DFB_CHECK(windata->window->RaiseToTop(windata->window));
   134 
   135     /* remember parent */
   136     windata->sdl_window = window;
   137 
   138     /* Add to list ... */
   139 
   140     windata->next = devdata->firstwin;
   141     windata->opacity = 0xFF;
   142     devdata->firstwin = windata;
   143 
   144     /* Draw Frame */
   145     DirectFB_WM_RedrawLayout(_this, window);
   146 
   147     return 0;
   148   error:
   149     SDL_DFB_RELEASE(windata->window);
   150     SDL_DFB_RELEASE(windata->surface);
   151     return -1;
   152 }
   153 
   154 int
   155 DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   156 {
   157     SDL_Unsupported();
   158     return -1;
   159 }
   160 
   161 void
   162 DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
   163 {
   164     SDL_DFB_WINDOWDATA(window);
   165 
   166     if (windata->is_managed) {
   167         windata->wm_needs_redraw = 1;
   168         DirectFB_WM_RedrawLayout(_this, window);
   169     } else
   170         SDL_Unsupported();
   171 }
   172 
   173 void
   174 DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   175 {
   176     SDL_DFB_DEVICEDATA(_this);
   177     SDL_DFB_WINDOWDATA(window);
   178     SDL_Surface *surface = NULL;
   179 
   180     if (icon) {
   181         SDL_PixelFormat format;
   182         DFBSurfaceDescription dsc;
   183         Uint32 *dest;
   184         Uint32 *p;
   185         int pitch, i;
   186 
   187         /* Convert the icon to ARGB for modern window managers */
   188         SDL_InitFormat(&format, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
   189                        0xFF000000);
   190         surface = SDL_ConvertSurface(icon, &format, 0);
   191         if (!surface) {
   192             return;
   193         }
   194         dsc.flags =
   195             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   196         dsc.caps = DSCAPS_VIDEOONLY;
   197         dsc.width = surface->w;
   198         dsc.height = surface->h;
   199         dsc.pixelformat = DSPF_ARGB;
   200 
   201         SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
   202                                                      &windata->icon));
   203 
   204         SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
   205                                              (void *) &dest, &pitch));
   206 
   207         p = surface->pixels;
   208         for (i = 0; i < surface->h; i++)
   209             memcpy((char *) dest + i * pitch,
   210                    (char *) p + i * surface->pitch, 4 * surface->w);
   211 
   212         SDL_DFB_CHECK(windata->icon->Unlock(windata->icon));
   213         SDL_FreeSurface(surface);
   214     } else {
   215         SDL_DFB_RELEASE(windata->icon);
   216     }
   217     return;
   218   error:
   219     if (surface)
   220         SDL_FreeSurface(surface);
   221     SDL_DFB_RELEASE(windata->icon);
   222     return;
   223 }
   224 
   225 void
   226 DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
   227 {
   228     SDL_DFB_WINDOWDATA(window);
   229     int x, y;
   230 
   231     if (window->y == SDL_WINDOWPOS_UNDEFINED)
   232         y = 0;
   233     else
   234         y = window->y;
   235 
   236     if (window->x == SDL_WINDOWPOS_UNDEFINED)
   237         x = 0;
   238     else
   239         x = window->x;
   240 
   241     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   242         x = 0;
   243         y = 0;
   244     }
   245     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   246     SDL_DFB_CHECK(windata->window->MoveTo(windata->window, x, y));
   247 }
   248 
   249 void
   250 DirectFB_SetWindowSize(_THIS, SDL_Window * window)
   251 {
   252     //SDL_DFB_DEVICEDATA(_this);
   253     SDL_DFB_WINDOWDATA(window);
   254 
   255     if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
   256         int cw;
   257         int ch;
   258 
   259         /* Make sure all events are disabled for this operation ! */
   260         SDL_DFB_CHECKERR(windata->window->DisableEvents(windata->window,
   261                                                         DWET_ALL));
   262 
   263         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));
   264 
   265         if (cw != window->w || ch != window->h) {
   266 
   267 		    DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   268             SDL_DFB_CHECKERR(windata->window->Resize(windata->window,
   269                                                      windata->size.w,
   270                                                      windata->size.h));
   271         }
   272 
   273         SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
   274                      (_this, window, &window->w, &window->h));
   275         DirectFB_AdjustWindowSurface(_this, window);
   276 
   277         SDL_DFB_CHECKERR(windata->window->EnableEvents(windata->window,
   278                                                        DWET_ALL));
   279 
   280     }
   281     return;
   282   error:
   283     SDL_DFB_CHECK(windata->window->EnableEvents(windata->window, DWET_ALL));
   284     return;
   285 }
   286 
   287 void
   288 DirectFB_ShowWindow(_THIS, SDL_Window * window)
   289 {
   290     SDL_DFB_WINDOWDATA(window);
   291 
   292     SDL_DFB_CHECK(windata->window->SetOpacity(windata->window, windata->opacity));
   293 
   294 }
   295 
   296 void
   297 DirectFB_HideWindow(_THIS, SDL_Window * window)
   298 {
   299     SDL_DFB_WINDOWDATA(window);
   300 
   301     SDL_DFB_CHECK(windata->window->GetOpacity(windata->window, &windata->opacity));
   302     SDL_DFB_CHECK(windata->window->SetOpacity(windata->window, 0));
   303 }
   304 
   305 void
   306 DirectFB_RaiseWindow(_THIS, SDL_Window * window)
   307 {
   308     SDL_DFB_WINDOWDATA(window);
   309 
   310     SDL_DFB_CHECK(windata->window->RaiseToTop(windata->window));
   311     SDL_DFB_CHECK(windata->window->RequestFocus(windata->window));
   312 }
   313 
   314 void
   315 DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
   316 {
   317     SDL_DFB_WINDOWDATA(window);
   318 
   319     if (windata->is_managed) {
   320         DirectFB_WM_MaximizeWindow(_this, window);
   321     } else
   322         SDL_Unsupported();
   323 }
   324 
   325 void
   326 DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
   327 {
   328     /* FIXME: Size to 32x32 ? */
   329 
   330     SDL_Unsupported();
   331 }
   332 
   333 void
   334 DirectFB_RestoreWindow(_THIS, SDL_Window * window)
   335 {
   336     SDL_DFB_WINDOWDATA(window);
   337 
   338     if (windata->is_managed) {
   339         DirectFB_WM_RestoreWindow(_this, window);
   340     } else
   341         SDL_Unsupported();
   342 }
   343 
   344 void
   345 DirectFB_SetWindowGrab(_THIS, SDL_Window * window)
   346 {
   347     SDL_DFB_DEVICEDATA(_this);
   348     SDL_DFB_WINDOWDATA(window);
   349     DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
   350 
   351     if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
   352         if (gwindata != NULL)
   353         {
   354 		    SDL_DFB_CHECK(gwindata->window->UngrabPointer(gwindata->window));
   355 		    SDL_DFB_CHECK(gwindata->window->UngrabKeyboard(gwindata->window));
   356         }
   357         SDL_DFB_CHECK(windata->window->GrabPointer(windata->window));
   358         SDL_DFB_CHECK(windata->window->GrabKeyboard(windata->window));
   359         devdata->grabbed_window = window;
   360     } else {
   361         SDL_DFB_CHECK(windata->window->UngrabPointer(windata->window));
   362         SDL_DFB_CHECK(windata->window->UngrabKeyboard(windata->window));
   363         devdata->grabbed_window = NULL;
   364     }
   365 }
   366 
   367 void
   368 DirectFB_DestroyWindow(_THIS, SDL_Window * window)
   369 {
   370     SDL_DFB_DEVICEDATA(_this);
   371     SDL_DFB_WINDOWDATA(window);
   372     DFB_WindowData *p;
   373 
   374     /* Some cleanups */
   375     SDL_DFB_CHECK(windata->window->UngrabPointer(windata->window));
   376     SDL_DFB_CHECK(windata->window->UngrabKeyboard(windata->window));
   377 
   378 #if SDL_DIRECTFB_OPENGL
   379 	DirectFB_GL_DestroyWindowContexts(_this, window);
   380 #endif
   381 
   382     SDL_DFB_CHECK(windata->window_surface->SetFont(windata->window_surface, NULL));
   383     SDL_DFB_CHECK(windata->surface->ReleaseSource(windata->surface));
   384     SDL_DFB_CHECK(windata->window_surface->ReleaseSource(windata->window_surface));
   385   	SDL_DFB_RELEASE(windata->icon);
   386     SDL_DFB_RELEASE(windata->font);
   387     SDL_DFB_RELEASE(windata->eventbuffer);
   388     SDL_DFB_RELEASE(windata->surface);
   389     SDL_DFB_RELEASE(windata->window_surface);
   390 
   391     SDL_DFB_RELEASE(windata->window);
   392 
   393     /* Remove from list ... */
   394 
   395     p = devdata->firstwin;
   396     while (p && p->next != windata)
   397         p = p->next;
   398     if (p)
   399         p->next = windata->next;
   400     else
   401         devdata->firstwin = windata->next;
   402     SDL_free(windata);
   403     return;
   404 }
   405 
   406 SDL_bool
   407 DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
   408                          struct SDL_SysWMinfo * info)
   409 {
   410     SDL_Unsupported();
   411     return SDL_FALSE;
   412 }
   413 
   414 static void
   415 DirectFB_AdjustWindowSurface(_THIS, SDL_Window * window)
   416 {
   417     SDL_DFB_WINDOWDATA(window);
   418     int adjust = windata->wm_needs_redraw;
   419     int cw, ch;
   420 
   421     DirectFB_WM_AdjustWindowLayout(window, window->flags, window->w, window->h);
   422 
   423     SDL_DFB_CHECKERR(windata->
   424                      window_surface->GetSize(windata->window_surface, &cw,
   425                                              &ch));
   426     if (cw != windata->size.w || ch != windata->size.h) {
   427         adjust = 1;
   428     }
   429 
   430     if (adjust) {
   431 #if SDL_DIRECTFB_OPENGL
   432 		DirectFB_GL_FreeWindowContexts(_this, window);
   433 #endif
   434 
   435 #if DFB_VERSION_ATLEAST(1,2,1)
   436         SDL_DFB_CHECKERR(windata->window->ResizeSurface(windata->window,
   437                                                         windata->size.w,
   438                                                         windata->size.h));
   439         SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
   440                                                           windata->
   441                                                           window_surface,
   442                                                           &windata->client));
   443 #else
   444         DFBWindowOptions opts;
   445 
   446         SDL_DFB_CHECKERR(windata->window->GetOptions(windata->window, &opts));
   447         /* recreate subsurface */
   448         SDL_DFB_RELEASE(windata->surface);
   449 
   450         if (opts & DWOP_SCALE)
   451             SDL_DFB_CHECKERR(windata->window->ResizeSurface(windata->window,
   452                                                             windata->size.w,
   453                                                             windata->size.h));
   454         SDL_DFB_CHECKERR(windata->window_surface->
   455                          GetSubSurface(windata->window_surface,
   456                                        &windata->client, &windata->surface));
   457 #endif
   458         DirectFB_WM_RedrawLayout(_this, window);
   459         
   460 #if SDL_DIRECTFB_OPENGL
   461 		DirectFB_GL_ReAllocWindowContexts(_this, window);
   462 #endif
   463    }
   464   error:
   465     return;
   466 }