glamor: Add prepare/finishaccess code based on UXA.

This commit is contained in:
Eric Anholt 2009-09-22 12:08:19 -07:00 committed by Zhigang Gong
parent f17473cdd5
commit c4343dfa0a
3 changed files with 269 additions and 2 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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,