From 6c2f1f0f86e7d8afe49cd8edbf34b91c7f3a461c Mon Sep 17 00:00:00 2001 From: Eli Gottlieb Date: Wed, 30 Jun 2010 16:19:44 -0400 Subject: [PATCH] Finished X11 shaped-window functionality and removed ellipse+polygon rendering. --- Makefile.in | 2 +- include/SDL_shape.h | 7 +-- include/SDL_video.h | 76 ------------------------------- src/video/SDL_shape.c | 85 ++++++++++++++++++++++++++++++++--- src/video/SDL_sysvideo.h | 42 +++++++++++++++-- src/video/SDL_video.c | 32 ------------- src/video/x11/SDL_x11shape.c | 67 ++++++++++++++++++++++++++- src/video/x11/SDL_x11video.c | 4 ++ src/video/x11/SDL_x11window.c | 3 ++ 9 files changed, 193 insertions(+), 125 deletions(-) diff --git a/Makefile.in b/Makefile.in index 4e2b185fe..ced88b314 100644 --- a/Makefile.in +++ b/Makefile.in @@ -44,7 +44,7 @@ EMBEDSPU = @EMBEDSPU@ DIST = acinclude autogen.sh Borland.html Borland.zip BUGS build-scripts configure configure.in COPYING CREDITS include INSTALL Makefile.minimal Makefile.in README* sdl-config.in sdl.m4 sdl.pc.in SDL.spec SDL.spec.in src test TODO VisualC.html VisualC VisualCE Watcom-Win32.zip WhatsNew Xcode Xcode-iPhoneOS -HDRS = SDL.h SDL_assert.h SDL_atomic.h SDL_audio.h SDL_compat.h SDL_cpuinfo.h SDL_ellipse.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_poly.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_shape.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h +HDRS = SDL.h SDL_assert.h SDL_atomic.h SDL_audio.h SDL_compat.h SDL_cpuinfo.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_shape.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ diff --git a/include/SDL_shape.h b/include/SDL_shape.h index f96769798..2c4ec7483 100644 --- a/include/SDL_shape.h +++ b/include/SDL_shape.h @@ -114,10 +114,11 @@ extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window,SDL_Surface *s * \brief Get the shape parameters of a shaped window. * * \param window The shaped window whose parameters should be retrieved. - * \param shapeMode An empty shape-parameters structure to fill. + * \param shapeMode An empty shape-mode structure to fill, or NULL to check whether the window has a shape. * - * \return 0 on success, -1 on a null shapeMode, or -2 if the SDL_Window given is not a shaped window, or -3 if the - * SDL_Window given is a window that can be shaped but isn't. + * \return 0 if the window has a shape and, provided shapeMode was not NULL, shapeMode has been filled with the mode + * data, -1 if the SDL_Window given is not a shaped window, or -2 if the SDL_Window* given is a shapeable + * window currently lacking a shape. * * \sa SDL_WindowShapeMode * \sa SDL_SetWindowShape diff --git a/include/SDL_video.h b/include/SDL_video.h index 557ed40e1..0ca914b38 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -1239,82 +1239,6 @@ extern DECLSPEC int SDLCALL SDL_RenderFillRect(const SDL_Rect * rect); */ extern DECLSPEC int SDLCALL SDL_RenderFillRects(const SDL_Rect ** rect, int count); -/** - * \brief Draw an ellipse on the current rendering target with the drawing color. - * - * \param ellipse The destination ellipse. - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderDrawEllipse(const SDL_Ellipse ellipse); - -/** - * \brief Draw some number of ellipses in the current rendering target with the drawing color. - * - * \param ellipse A pointer to an array of destination ellipses. - * \param count The number of ellipses. - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderDrawEllipses(const SDL_Ellipse * ellipse, int count); - -/** - * \brief Fill an ellipse on the current rendering target with the drawing color. - * - * \param ellipse The destination ellipse - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderFillEllipse(const SDL_Ellipse ellipse); - -/** - * \brief Fill some number of ellipses in the current rendering target with the drawing color. - * - * \param ellipse A pointer to an array of destination ellipses. - * \param count The number of ellipses. - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderFillEllipses(const SDL_Ellipse *ellipse, int count); - -/** - * \brief Draw a polygon on the current rendering target with the drawing color. - * - * \param poly The destination polygon. - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderDrawPoly(const SDL_Poly poly); - -/** - * \brief Draw some number of polygons in the current rendering target with the drawing color. - * - * \param poly A pointer to an array of destination polygons. - * \param count The number of polygons. - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderDrawPolys(const SDL_Poly *poly, int count); - -/** - * \brief Fill a polygon on the current rendering target with the drawing color. - * - * \param poly The destination polygon - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderFillPoly(const SDL_Poly poly); - -/** - * \brief Fill some number of polygons in the current rendering target with the drawing color. - * - * \param poly A pointer to an array of destination polygons. - * \param count The number of polygons. - * - * \return 0 on success, or -1 if there is no rendering context current. - */ -extern DECLSPEC int SDLCALL SDL_RenderFillPolys(const SDL_Poly *poly, int count); - /** * \brief Copy a portion of the texture to the current rendering target. * diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c index c38fc47b3..2d65619da 100644 --- a/src/video/SDL_shape.c +++ b/src/video/SDL_shape.c @@ -24,28 +24,99 @@ #include "SDL.h" #include "SDL_video.h" #include "SDL_sysvideo.h" +#include "SDL_pixels.h" +#include "SDL_surface.h" #include "SDL_shape.h" SDL_Window* SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags) { - return NULL; + SDL_Window *result = SDL_CreateWindow(title,x,y,w,h,SDL_WINDOW_BORDERLESS | flags & !SDL_WINDOW_FULLSCREEN & !SDL_WINDOW_SHOWN); + result->shaper = result->display->device->shape_driver.CreateShaper(result); + result->shaper->usershownflag = flags & SDL_WINDOW_SHOWN; + result->shaper->alphacutoff = 1; + result->shaper->hasshape = SDL_FALSE; + return result; } SDL_bool SDL_IsShapedWindow(const SDL_Window *window) { - return SDL_FALSE; + if(window == NULL) + return SDL_FALSE; + else + return window->shaper != NULL; +} + +/* REQUIRES that bitmap point to a w-by-h bitmap with 1bpp. */ +void SDL_CalculateShapeBitmap(Uint8 alphacutoff,SDL_Surface *shape,Uint8* bitmap) { + if(SDL_MUSTLOCK(shape)) + SDL_LockSurface(shape); + int x = 0,y = 0; + for(x = 0;xw;x++) + for(y = 0;yh;y++) { + void* pixel = shape->pixels + (y*shape->pitch) + (x*shape->format->BytesPerPixel); + Uint8 alpha = 0; + SDL_GetRGBA(*(Uint32*)pixel,shape->format,NULL,NULL,NULL,&alpha); + Uint32 bitmap_pixel = y*shape->w + x; + bitmap[bitmap_pixel / 8] |= (alpha >= alphacutoff ? 1 : 0) << (8 - (bitmap_pixel % 8)); + } + if(SDL_MUSTLOCK(shape)) + SDL_UnlockSurface(shape); } int SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) { if(window == NULL || !SDL_WindowIsShaped(window)) + //The window given was not a shapeable window. return -2; if(shape == NULL) + //Invalid shape argument. return -1; - return -3; + + if(shapeMode != NULL) { + switch(shapeMode->mode) { + case ShapeModeDefault: { + window->shaper->alphacutoff = 1; + break; + } + case ShapeModeBinarizeAlpha: { + window->shaper->alphacutoff = shapeMode->parameters.binarizationCutoff; + break; + } + } + } + //TODO: Platform-specific implementations of SetWindowShape. X11 is in-progress. + int result = window->display->device->shape_driver.SetWindowShape(window->shaper,shape,shapeMode); + window->shaper->hasshape = SDL_TRUE; + if(window->shaper->usershownflag & SDL_WINDOW_SHOWN == SDL_WINDOW_SHOWN) { + SDL_ShowWindow(window); + window->shaper->usershownflag &= !SDL_WINDOW_SHOWN; + } + return result; +} + +SDL_bool SDL_WindowHasAShape(SDL_Window *window) { + assert(window != NULL && SDL_IsShapedWindow(window)); + return window->shaper->hasshape; } int SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shapeMode) { - if(shapeMode == NULL) + if(window != NULL && SDL_IsShapedWindow(window)) { + if(shapeMode == NULL) { + if(SDL_WindowHasAShape(window)) + //The window given has a shape. + return 0; + else + //The window given is shapeable but lacks a shape. + return -2; + } + else { + if(window->shaper->alphacutoff != 1) { + shapeMode->mode = ShapeModeBinarizeAlpha; + shapeMode->parameters.binarizationCutoff = window->shaper->alphacutoff; + } + else + shapeMode->mode = ShapeModeDefault; + return 0; + } + } + else + //The window given is not a valid shapeable window. return -1; - if(window == NULL || !SDL_WindowIsShaped(window)) - return -2; - return -3; } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index bc2991287..2e4980048 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -26,11 +26,14 @@ #include "SDL_mouse.h" #include "SDL_keysym.h" +#include "SDL_shape.h" /* The SDL video driver */ typedef struct SDL_Renderer SDL_Renderer; typedef struct SDL_RenderDriver SDL_RenderDriver; +typedef struct SDL_WindowShaper SDL_WindowShaper; +typedef struct SDL_ShapeDriver SDL_ShapeDriver; typedef struct SDL_VideoDisplay SDL_VideoDisplay; typedef struct SDL_VideoDevice SDL_VideoDevice; @@ -97,10 +100,6 @@ struct SDL_Renderer int count); int (*RenderFillRects) (SDL_Renderer * renderer, const SDL_Rect ** rects, int count); - int (*RenderDrawEllipse) (SDL_Renderer * renderer, int x, int y, - int w, int h); - int (*RenderFillEllipse) (SDL_Renderer * renderer, int x, int y, - int w, int h); int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect); int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect, @@ -136,6 +135,33 @@ struct SDL_RenderDriver SDL_RendererInfo info; }; +/* Define the SDL window-shaper structure */ +struct SDL_WindowShaper +{ + /* The window associated with the shaper */ + SDL_Window *window; + + /* The user's specified SDL_WINDOW_SHOWN flag, for use once the user gives the window a shape. */ + Uint32 usershownflag; + + /* The cutoff value for alpha-channel binarization. When alpha is greater-than-or-equal-to this value in the shape + image, the corresponding pixel of the actual window will be considered part of the window's shape. */ + Uint8 alphacutoff; + + /* Has this window been assigned a shape? */ + SDL_bool hasshape; + + void *driverdata; +}; + +/* Define the SDL shape driver structure */ +struct SDL_ShapeDriver +{ + SDL_WindowShaper *(*CreateShaper)(SDL_Window * window); + int (*SetWindowShape)(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode); + int (*ResizeWindowShape)(SDL_Window *window); +}; + /* Define the SDL window structure, corresponding to toplevel windows */ struct SDL_Window { @@ -150,6 +176,8 @@ struct SDL_Window SDL_Renderer *renderer; SDL_DisplayMode fullscreen_mode; + + SDL_WindowShaper *shaper; void *userdata; void *driverdata; @@ -270,6 +298,12 @@ struct SDL_VideoDevice void (*RestoreWindow) (_THIS, SDL_Window * window); void (*SetWindowGrab) (_THIS, SDL_Window * window); void (*DestroyWindow) (_THIS, SDL_Window * window); + + /* * * */ + /* + * Shaped-window functions + */ + SDL_ShapeDriver shape_driver; /* Get some platform dependent window information */ SDL_bool(*GetWindowWMInfo) (_THIS, SDL_Window * window, diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 2f9b27642..8ac0d1d4c 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2534,38 +2534,6 @@ SDL_RenderFillRects(const SDL_Rect ** rects, int count) return renderer->RenderFillRects(renderer, rects, count); } -int SDL_RenderDrawEllipse(const SDL_Ellipse ellipse) { - return SDL_RenderDrawEllipses(&ellipse,1); -} - -int SDL_RenderDrawEllipses(const SDL_Ellipse * ellipse, int count) { - return -1; -} - -int SDL_RenderFillEllipse(const SDL_Ellipse ellipse) { - return SDL_RenderFillEllipses(&ellipse,1); -} - -int SDL_RenderFillEllipses(const SDL_Ellipse * ellipse, int count) { - return -1; -} - -int SDL_RenderDrawPoly(const SDL_Poly poly) { - return SDL_RenderDrawPolys(&poly,1); -} - -int SDL_RenderDrawPolys(const SDL_Poly *poly, int count) { - return -1; -} - -int SDL_RenderFillPoly(const SDL_Poly poly) { - return SDL_RenderFillPolys(&poly,1); -} - -int SDL_RenderFillPolys(const SDL_Poly *poly, int count) { - return -1; -} - int SDL_RenderCopy(SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect) diff --git a/src/video/x11/SDL_x11shape.c b/src/video/x11/SDL_x11shape.c index 4a2f1d27b..e1600818c 100644 --- a/src/video/x11/SDL_x11shape.c +++ b/src/video/x11/SDL_x11shape.c @@ -20,6 +20,69 @@ eligottlieb@gmail.com */ -#include "SDL_shape.h" +#include +#include +#include +#include +#include +#include "SDL_x11shape.h" +#include "SDL_x11window.h" +#include "SDL_x11video.h" -/* Functions implementing shaped-window functionality for X Window System will be implemented when the API is decided. */ +SDL_WindowShaper* X11_CreateShaper(SDL_Window* window) { + SDL_WindowShaper* result = malloc(sizeof(SDL_WindowShaper)); + result->window = window; + result->alphacutoff = 0; + result->usershownflag = 0; + result->driverdata = malloc(sizeof(SDL_ShapeData)); + window->shaper = result; + int resized_properly = X11ResizeWindowShape(window); + assert(resized_properly == 0); + return result; +} + +int X11_ResizeWindowShape(SDL_Window* window) { + SDL_ShapeData* data = window->shaper->driverdata; + assert(data != NULL); + + unsigned int bitmapsize = window->w / 8; + if(window->w % 8 > 0) + bitmapsize += 1; + bitmapsize *= window->h; + if(data->bitmapsize != bitmapsize || data->bitmap == NULL) { + data->bitmapsize = bitmapsize; + if(data->bitmap != NULL) + free(data->bitmap); + data->bitmap = malloc(data->bitmapsize); + if(data->bitmap == NULL) { + SDL_SetError("Could not allocate memory for shaped-window bitmap."); + return -1; + } + } + + window->shaper->usershownflag = window->flags & SDL_WINDOW_SHOWN; + + return 0; +} + +int X11_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode) { + if(!SDL_ISPIXELFORMAT_ALPHA(SDL_MasksToPixelFormatEnum(shape->format->BitsPerPixel,shape->format->Rmask,shape->format->Gmask,shape->format->Bmask,shape->format->Amask))) + return -2; + if(shape->w != shaper->window->w || shape->h != shaper->window->h) + return -3; + SDL_ShapeData *data = shaper->driverdata; + assert(data != NULL); + + /* Assume that shaper->alphacutoff already has a value. */ + SDL_CalculateShapeBitmap(shaper->alphacutoff,shape,data->bitmap); + + SDL_WindowData *windowdata = (SDL_WindowData*)(shaper->window->driverdata); + Pixmap shapemask = XCreateBitmapFromData(windowdata->videodata->display,windowdata->xwindow,data->bitmap,shaper->window->w,shaper->window->h); + + XShapeCombineMask(windowdata->videodata->display,windowdata->xwindow, ShapeBounding, 0, 0,shapemask, ShapeSet); + XSync(windowdata->videodata->display,False); + + XFreePixmap(windowdata->videodata->display,shapemask); + + return 0; +} diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 2494bce39..b320aaafe 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -28,6 +28,7 @@ #include "SDL_x11video.h" #include "SDL_x11render.h" +#include "SDL_x11shape.h" #if SDL_VIDEO_DRIVER_PANDORA #include "SDL_x11opengles.h" @@ -202,6 +203,9 @@ X11_CreateDevice(int devindex) device->SetWindowGrab = X11_SetWindowGrab; device->DestroyWindow = X11_DestroyWindow; device->GetWindowWMInfo = X11_GetWindowWMInfo; + device->shape_driver.CreateShaper = X11_CreateShaper; + device->shape_driver.SetWindowShape = X11_SetWindowShape; + device->shape_driver.ResizeWindowShape = X11_ResizeWindowShape; #ifdef SDL_VIDEO_OPENGL_GLX device->GL_LoadLibrary = X11_GL_LoadLibrary; device->GL_GetProcAddress = X11_GL_GetProcAddress; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 18c0e478e..c7742e262 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -28,6 +28,7 @@ #include "SDL_x11video.h" #include "SDL_x11mouse.h" #include "SDL_x11gamma.h" +#include "SDL_x11shape.h" #include "../Xext/extensions/StdCmap.h" #ifdef SDL_VIDEO_DRIVER_PANDORA @@ -897,6 +898,8 @@ X11_SetWindowSize(_THIS, SDL_Window * window) SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; + if(SDL_IsShapedWindow(window)) + X11_ResizeWindowShape(window); XResizeWindow(display, data->xwindow, window->w, window->h); }