glamor: Add prepare/finishaccess code based on UXA.
This commit is contained in:
		
							parent
							
								
									f17473cdd5
								
							
						
					
					
						commit
						c4343dfa0a
					
				|  | @ -177,6 +177,10 @@ glamor_init(ScreenPtr screen) | |||
| 	ErrorF("GL_ARB_vertex_shader required\n"); | ||||
| 	goto fail; | ||||
|     } | ||||
|     if (!GLEW_ARB_pixel_buffer_object) { | ||||
| 	ErrorF("GL_ARB_pixel_buffer_object required\n"); | ||||
| 	goto fail; | ||||
|     } | ||||
| 
 | ||||
|     if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, | ||||
| 					glamor_wakeup_handler, | ||||
|  | @ -199,6 +203,12 @@ glamor_init(ScreenPtr screen) | |||
|     glamor_priv->saved_get_image = screen->GetImage; | ||||
|     screen->GetImage = miGetImage; | ||||
| 
 | ||||
|     glamor_priv->saved_change_window_attributes = screen->ChangeWindowAttributes; | ||||
|     screen->ChangeWindowAttributes = glamor_change_window_attributes; | ||||
| 
 | ||||
|     glamor_priv->saved_bitmap_to_region = screen->BitmapToRegion; | ||||
|     screen->BitmapToRegion = glamor_bitmap_to_region; | ||||
| 
 | ||||
| #ifdef RENDER | ||||
|     glamor_priv->saved_composite = ps->Composite; | ||||
|     ps->Composite = glamor_composite; | ||||
|  | @ -231,6 +241,8 @@ glamor_fini(ScreenPtr screen) | |||
|     screen->CreatePixmap = glamor_priv->saved_create_pixmap; | ||||
|     screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; | ||||
|     screen->GetSpans = glamor_priv->saved_get_spans; | ||||
|     screen->ChangeWindowAttributes = glamor_priv->saved_change_window_attributes; | ||||
|     screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; | ||||
| #ifdef RENDER | ||||
|     ps->Composite = glamor_priv->saved_composite; | ||||
| #endif | ||||
|  |  | |||
|  | @ -260,6 +260,129 @@ glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, | |||
|     } | ||||
| } | ||||
| 
 | ||||
| Bool | ||||
| glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) | ||||
| { | ||||
|     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); | ||||
|     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); | ||||
|     unsigned int stride; | ||||
|     GLenum format, type; | ||||
| 
 | ||||
|     if (pixmap_priv == NULL) | ||||
| 	return TRUE; | ||||
| 
 | ||||
|     if (pixmap_priv->fb == 0) { | ||||
| 	ScreenPtr screen = pixmap->drawable.pScreen; | ||||
| 	PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); | ||||
| 
 | ||||
| 	if (pixmap != screen_pixmap) | ||||
| 	    return TRUE; | ||||
|     } | ||||
| 
 | ||||
|     stride = PixmapBytePad(drawable->width, drawable->depth); | ||||
| 
 | ||||
|     switch (drawable->depth) { | ||||
|     case 1: | ||||
| 	format = GL_COLOR_INDEX; | ||||
| 	type = GL_BITMAP; | ||||
| 	break; | ||||
|     case 8: | ||||
| 	format = GL_ALPHA; | ||||
| 	type = GL_UNSIGNED_BYTE; | ||||
| 	break; | ||||
|     case 24: | ||||
| 	format = GL_RGB; | ||||
| 	type = GL_UNSIGNED_BYTE; | ||||
| 	break; | ||||
|     case 32: | ||||
| 	format = GL_BGRA; | ||||
| 	type = GL_UNSIGNED_INT_8_8_8_8_REV; | ||||
| 	break; | ||||
|     default: | ||||
| 	ErrorF("Unknown prepareaccess depth %d\n", drawable->depth); | ||||
| 	return FALSE; | ||||
|     } | ||||
| 
 | ||||
|     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); | ||||
|     glGenBuffersARB(1, &pixmap_priv->pbo); | ||||
|     glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); | ||||
|     glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, stride * drawable->height, | ||||
| 		    NULL, GL_DYNAMIC_DRAW_ARB); | ||||
|     glPixelStorei(GL_PACK_ALIGNMENT, 1); | ||||
|     glPixelStorei(GL_PACK_ROW_LENGTH, stride * 8 / | ||||
| 		  pixmap->drawable.bitsPerPixel); | ||||
| 
 | ||||
|     glReadPixels(0, 0, | ||||
| 		 pixmap->drawable.width, pixmap->drawable.height, | ||||
| 		 format, type, 0); | ||||
| 
 | ||||
|     pixmap->devPrivate.ptr = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, | ||||
| 					    GL_READ_WRITE_ARB); | ||||
| 
 | ||||
|     return TRUE; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| glamor_finish_access(DrawablePtr drawable) | ||||
| { | ||||
|     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); | ||||
|     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); | ||||
|     unsigned int stride; | ||||
|     GLenum format, type; | ||||
| 
 | ||||
|     if (pixmap_priv == NULL) | ||||
| 	return; | ||||
| 
 | ||||
|     if (pixmap_priv->fb == 0) { | ||||
| 	ScreenPtr screen = pixmap->drawable.pScreen; | ||||
| 	PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); | ||||
| 
 | ||||
| 	if (pixmap != screen_pixmap) | ||||
| 	    return; | ||||
|     } | ||||
| 
 | ||||
|     glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); | ||||
|     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); | ||||
|     glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); | ||||
|     pixmap->devPrivate.ptr = NULL; | ||||
| 
 | ||||
|     stride = PixmapBytePad(drawable->width, drawable->depth); | ||||
| 
 | ||||
|     switch (drawable->depth) { | ||||
|     case 1: | ||||
| 	format = GL_COLOR_INDEX; | ||||
| 	type = GL_BITMAP; | ||||
| 	break; | ||||
|     case 8: | ||||
| 	format = GL_ALPHA; | ||||
| 	type = GL_UNSIGNED_BYTE; | ||||
| 	break; | ||||
|     case 24: | ||||
| 	format = GL_RGB; | ||||
| 	type = GL_UNSIGNED_BYTE; | ||||
| 	break; | ||||
|     case 32: | ||||
| 	format = GL_BGRA; | ||||
| 	type = GL_UNSIGNED_INT_8_8_8_8_REV; | ||||
| 	break; | ||||
|     default: | ||||
| 	ErrorF("Unknown finishaccess depth %d\n", drawable->depth); | ||||
| 	return; | ||||
|     } | ||||
| 
 | ||||
|     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); | ||||
|     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); | ||||
|     glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|     glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8 / | ||||
| 		  pixmap->drawable.bitsPerPixel); | ||||
| 
 | ||||
|     glRasterPos2i(0, 0); | ||||
|     glDrawPixels(pixmap->drawable.width, pixmap->drawable.height, | ||||
| 		 format, type, 0); | ||||
|     glDeleteBuffersARB(1, &pixmap_priv->pbo); | ||||
|     glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, | ||||
| 	       int x, int y, int width, int height, | ||||
|  | @ -364,13 +487,78 @@ GCOps glamor_gc_ops = { | |||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * exaValidateGC() sets the ops to EXA's implementations, which may be | ||||
|  * uxa_validate_gc() sets the ops to glamor's implementations, which may be | ||||
|  * accelerated or may sync the card and fall back to fb. | ||||
|  */ | ||||
| static void | ||||
| glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) | ||||
| { | ||||
|     fbValidateGC(gc, changes, drawable); | ||||
|     /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
 | ||||
|      * Preempt fbValidateGC by doing its work and masking the change out, so | ||||
|      * that we can do the Prepare/finish_access. | ||||
|      */ | ||||
| #ifdef FB_24_32BIT | ||||
|     if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { | ||||
| 	gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); | ||||
| 	fbGetRotatedPixmap(gc) = 0; | ||||
|     } | ||||
| 
 | ||||
|     if (gc->fillStyle == FillTiled) { | ||||
| 	PixmapPtr old_tile, new_tile; | ||||
| 
 | ||||
| 	old_tile = gc->tile.pixmap; | ||||
| 	if (old_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { | ||||
| 	    new_tile = fbGetRotatedPixmap(gc); | ||||
| 	    if (!new_tile || | ||||
| 		new_tile ->drawable.bitsPerPixel != drawable->bitsPerPixel) | ||||
| 	    { | ||||
| 		if (new_tile) | ||||
| 		    gc->pScreen->DestroyPixmap(new_tile); | ||||
| 		/* fb24_32ReformatTile will do direct access of a newly-
 | ||||
| 		 * allocated pixmap. | ||||
| 		 */ | ||||
| 		if (glamor_prepare_access(&old_tile->drawable, | ||||
| 					  GLAMOR_ACCESS_RO)) { | ||||
| 		    new_tile = fb24_32ReformatTile(old_tile, | ||||
| 						   drawable->bitsPerPixel); | ||||
| 		    glamor_finish_access(&old_tile->drawable); | ||||
| 		} | ||||
| 	    } | ||||
| 	    if (new_tile) { | ||||
| 		fbGetRotatedPixmap(gc) = old_tile; | ||||
| 		gc->tile.pixmap = new_tile; | ||||
| 		changes |= GCTile; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| #endif | ||||
|     if (changes & GCTile) { | ||||
| 	if (!gc->tileIsPixel && FbEvenTile(gc->tile.pixmap->drawable.width * | ||||
| 					   drawable->bitsPerPixel)) | ||||
| 	{ | ||||
| 	    if (glamor_prepare_access(&gc->tile.pixmap->drawable, | ||||
| 				      GLAMOR_ACCESS_RW)) { | ||||
| 		fbPadPixmap(gc->tile.pixmap); | ||||
| 		glamor_finish_access(&gc->tile.pixmap->drawable); | ||||
| 	    } | ||||
| 	} | ||||
| 	/* Mask out the GCTile change notification, now that we've done FB's
 | ||||
| 	 * job for it. | ||||
| 	 */ | ||||
| 	changes &= ~GCTile; | ||||
|     } | ||||
| 
 | ||||
|     if (changes & GCStipple && gc->stipple) { | ||||
| 	/* We can't inline stipple handling like we do for GCTile because
 | ||||
| 	 * it sets fbgc privates. | ||||
| 	 */ | ||||
| 	if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { | ||||
| 	    fbValidateGC(gc, changes, drawable); | ||||
| 	    glamor_finish_access(&gc->stipple->drawable); | ||||
| 	} | ||||
|     } else { | ||||
| 	fbValidateGC(gc, changes, drawable); | ||||
|     } | ||||
| 
 | ||||
|     gc->ops = &glamor_gc_ops; | ||||
| } | ||||
|  | @ -399,3 +587,56 @@ glamor_create_gc(GCPtr gc) | |||
| 
 | ||||
|     return TRUE; | ||||
| } | ||||
| 
 | ||||
| Bool | ||||
| glamor_prepare_access_window(WindowPtr window) | ||||
| { | ||||
|     if (window->backgroundState == BackgroundPixmap) { | ||||
|         if (!glamor_prepare_access(&window->background.pixmap->drawable, | ||||
| 				   GLAMOR_ACCESS_RO)) | ||||
| 	    return FALSE; | ||||
|     } | ||||
| 
 | ||||
|     if (window->borderIsPixel == FALSE) { | ||||
|         if (!glamor_prepare_access(&window->border.pixmap->drawable, | ||||
| 				   GLAMOR_ACCESS_RO)) { | ||||
| 	    if (window->backgroundState == BackgroundPixmap) | ||||
| 		glamor_finish_access(&window->background.pixmap->drawable); | ||||
| 	    return FALSE; | ||||
| 	} | ||||
|     } | ||||
|     return TRUE; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| glamor_finish_access_window(WindowPtr window) | ||||
| { | ||||
|     if (window->backgroundState == BackgroundPixmap) | ||||
|         glamor_finish_access(&window->background.pixmap->drawable); | ||||
| 
 | ||||
|     if (window->borderIsPixel == FALSE) | ||||
|         glamor_finish_access(&window->border.pixmap->drawable); | ||||
| } | ||||
| 
 | ||||
| Bool | ||||
| glamor_change_window_attributes(WindowPtr window, unsigned long mask) | ||||
| { | ||||
|     Bool ret; | ||||
| 
 | ||||
|     if (!glamor_prepare_access_window(window)) | ||||
| 	return FALSE; | ||||
|     ret = fbChangeWindowAttributes(window, mask); | ||||
|     glamor_finish_access_window(window); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| RegionPtr | ||||
| glamor_bitmap_to_region(PixmapPtr pixmap) | ||||
| { | ||||
|   RegionPtr ret; | ||||
|   if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) | ||||
|     return NULL; | ||||
|   ret = fbPixmapToRegion(pixmap); | ||||
|   glamor_finish_access(&pixmap->drawable); | ||||
|   return ret; | ||||
| } | ||||
|  |  | |||
|  | @ -31,6 +31,11 @@ | |||
| #include "glamor.h" | ||||
| #include <GL/glew.h> | ||||
| 
 | ||||
| typedef enum glamor_access { | ||||
|     GLAMOR_ACCESS_RO, | ||||
|     GLAMOR_ACCESS_RW, | ||||
| } glamor_access_t; | ||||
| 
 | ||||
| typedef struct glamor_transform_uniforms { | ||||
|     GLint x_bias; | ||||
|     GLint x_scale; | ||||
|  | @ -55,6 +60,8 @@ typedef struct glamor_screen_private { | |||
|     GetImageProcPtr saved_get_image; | ||||
|     CompositeProcPtr saved_composite; | ||||
|     TrapezoidsProcPtr saved_trapezoids; | ||||
|     ChangeWindowAttributesProcPtr saved_change_window_attributes; | ||||
|     BitmapToRegionProcPtr saved_bitmap_to_region; | ||||
| 
 | ||||
|     /* glamor_solid */ | ||||
|     GLint solid_prog; | ||||
|  | @ -78,6 +85,7 @@ typedef struct glamor_screen_private { | |||
| typedef struct glamor_pixmap_private { | ||||
|     GLuint tex; | ||||
|     GLuint fb; | ||||
|     GLuint pbo; | ||||
| } glamor_pixmap_private; | ||||
| 
 | ||||
| extern DevPrivateKey glamor_screen_private_key; | ||||
|  | @ -117,6 +125,10 @@ RegionPtr | |||
| glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, | ||||
| 		 int srcx, int srcy, int width, int height, int dstx, int dsty); | ||||
| /* glamor_core.c */ | ||||
| Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access); | ||||
| void glamor_finish_access(DrawablePtr drawable); | ||||
| Bool glamor_prepare_access_window(WindowPtr window); | ||||
| void glamor_finish_access_window(WindowPtr window); | ||||
| Bool glamor_create_gc(GCPtr gc); | ||||
| void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, | ||||
| 		    int x, int y, int width, int height, | ||||
|  | @ -134,6 +146,8 @@ void glamor_get_transform_uniform_locations(GLint prog, | |||
| 					    glamor_transform_uniforms *uniform_locations); | ||||
| void glamor_set_transform_for_pixmap(PixmapPtr pixmap, | ||||
| 				     glamor_transform_uniforms *uniform_locations); | ||||
| Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); | ||||
| RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); | ||||
| 
 | ||||
| /* glamor_fill.c */ | ||||
| void glamor_fill(DrawablePtr drawable, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue