Finished X11 shaped-window functionality and removed ellipse+polygon rendering.
authorEli Gottlieb <eligottlieb@gmail.com>
Wed, 30 Jun 2010 16:19:44 -0400
changeset 4782 b6930aefd008
parent 4781 fc4c775b468a
child 4783 43826836b995
Finished X11 shaped-window functionality and removed ellipse+polygon rendering.
Makefile.in
include/SDL_shape.h
include/SDL_video.h
src/video/SDL_shape.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/x11/SDL_x11shape.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11window.c
--- a/Makefile.in	Mon Jun 21 23:08:10 2010 -0400
+++ b/Makefile.in	Wed Jun 30 16:19:44 2010 -0400
@@ -44,7 +44,7 @@
 
 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@
--- a/include/SDL_shape.h	Mon Jun 21 23:08:10 2010 -0400
+++ b/include/SDL_shape.h	Wed Jun 30 16:19:44 2010 -0400
@@ -114,10 +114,11 @@
  * \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
--- a/include/SDL_video.h	Mon Jun 21 23:08:10 2010 -0400
+++ b/include/SDL_video.h	Wed Jun 30 16:19:44 2010 -0400
@@ -1240,82 +1240,6 @@
 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.
  *  
  *  \param texture The source texture.
--- a/src/video/SDL_shape.c	Mon Jun 21 23:08:10 2010 -0400
+++ b/src/video/SDL_shape.c	Wed Jun 30 16:19:44 2010 -0400
@@ -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;x<shape->w;x++)
+		for(y = 0;y<shape->h;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;
 }
--- a/src/video/SDL_sysvideo.h	Mon Jun 21 23:08:10 2010 -0400
+++ b/src/video/SDL_sysvideo.h	Wed Jun 30 16:19:44 2010 -0400
@@ -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 @@
                             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 @@
     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 @@
     SDL_Renderer *renderer;
 
     SDL_DisplayMode fullscreen_mode;
+    
+    SDL_WindowShaper *shaper;
 
     void *userdata;
     void *driverdata;
@@ -270,6 +298,12 @@
     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,
--- a/src/video/SDL_video.c	Mon Jun 21 23:08:10 2010 -0400
+++ b/src/video/SDL_video.c	Wed Jun 30 16:19:44 2010 -0400
@@ -2534,38 +2534,6 @@
     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)
--- a/src/video/x11/SDL_x11shape.c	Mon Jun 21 23:08:10 2010 -0400
+++ b/src/video/x11/SDL_x11shape.c	Wed Jun 30 16:19:44 2010 -0400
@@ -20,6 +20,69 @@
     eligottlieb@gmail.com
 */
 
-#include "SDL_shape.h"
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Converters.h>
+#include <X11/extensions/shape.h>
+#include "SDL_x11shape.h"
+#include "SDL_x11window.h"
+#include "SDL_x11video.h"
+
+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;
+}
 
-/* Functions implementing shaped-window functionality for X Window System will be implemented when the API is decided. */
+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;
+}
--- a/src/video/x11/SDL_x11video.c	Mon Jun 21 23:08:10 2010 -0400
+++ b/src/video/x11/SDL_x11video.c	Wed Jun 30 16:19:44 2010 -0400
@@ -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 @@
     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;
--- a/src/video/x11/SDL_x11window.c	Mon Jun 21 23:08:10 2010 -0400
+++ b/src/video/x11/SDL_x11window.c	Wed Jun 30 16:19:44 2010 -0400
@@ -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 @@
     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);
 }