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
Block a user