summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-03-20 12:47:12 +1000
committerDave Airlie <airlied@gmail.com>2013-03-20 17:25:44 +1000
commit6bc49646f114a13dd47a71dc68f0d079ad791a32 (patch)
tree311859c7047f4ac907dc748c61aac129f11e3c2d
parenta0ba7a0b25dfdccb049f6b61342e78f73f2cb70a (diff)
qxl: flip dri2 surface into sw renderer modedri2-hacks
Instead of involving the hw when we get a front request for a dri2 buffer, just flip it into magic sw rendered mode, and turn it the right way up. If we ever fix cogl then we can avoid the turning it upside down bit, but its just once per redirected pixmap, at startup.
-rw-r--r--src/qxl_dri2.c13
-rw-r--r--src/qxl_kms.c1
-rw-r--r--src/qxl_surface.c63
-rw-r--r--src/qxl_surface.h3
-rw-r--r--src/qxl_surface_ums.c2
5 files changed, 80 insertions, 2 deletions
diff --git a/src/qxl_dri2.c b/src/qxl_dri2.c
index e4242d6..ebd4976 100644
--- a/src/qxl_dri2.c
+++ b/src/qxl_dri2.c
@@ -82,9 +82,22 @@ qxl_dri2_create_buffer2(ScreenPtr screen, DrawablePtr draw, unsigned int attachm
return NULL;
if (attachment == DRI2BufferFrontLeft) {
+ struct qxl_surface_t *surf;
ppix = get_drawable_pixmap(draw);
if (ppix)
ppix->refcnt++;
+
+ /* okay flip */
+
+ /* get name */
+ surf = get_surface(ppix);
+ if (ppix->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP) {
+ if (!surf->dri2_sw_rendered) {
+ qxl_flip_surface(surf);
+ }
+ surf->dri2_sw_rendered = TRUE;
+
+ }
} else {
int bpp;
unsigned int usage_hint = 0;
diff --git a/src/qxl_kms.c b/src/qxl_kms.c
index 319f056..4c89141 100644
--- a/src/qxl_kms.c
+++ b/src/qxl_kms.c
@@ -688,6 +688,7 @@ qxl_kms_surface_create(qxl_screen_t *qxl,
surface->qxl = qxl;
surface->id = bo->handle;
surface->image_bo = NULL;
+ surface->dri2_sw_rendered = FALSE;
if (usage_hint & QXL_CREATE_PIXMAP_DRI2)
surface->is_dri2_surf = TRUE;
else
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 0c70416..55f18b6 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -160,6 +160,19 @@ qxl_surface_prepare_access (qxl_surface_t *surface,
if (!pScrn->vtSema)
return FALSE;
+ if (surface->dri2_sw_rendered || surface->is_dri2_surf) {
+ void *map = surface->qxl->bo_funcs->bo_map(surface->bo);
+
+ pScreen->ModifyPixmapHeader(
+ pixmap,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ -1, -1, -1, map);
+
+ pixmap->devKind = abs(pixman_image_get_stride (surface->host_image));
+ return TRUE;
+ }
+
REGION_INIT (NULL, &new, (BoxPtr)NULL, 0);
REGION_SUBTRACT (NULL, &new, region, &surface->access_region);
@@ -343,6 +356,11 @@ qxl_surface_finish_access (qxl_surface_t *surface, PixmapPtr pixmap)
int n_boxes;
BoxPtr boxes;
+ if (surface->dri2_sw_rendered) {
+ pScreen->ModifyPixmapHeader(pixmap, w, h, -1, -1, 0, NULL);
+ surface->qxl->bo_funcs->bo_unmap(surface->bo);
+ return;
+ }
n_boxes = REGION_NUM_RECTS (&surface->access_region);
boxes = REGION_RECTS (&surface->access_region);
@@ -404,6 +422,9 @@ Bool
qxl_surface_prepare_solid (qxl_surface_t *destination,
Pixel fg)
{
+ if (destination->dri2_sw_rendered)
+ return FALSE;
+
if (!REGION_NIL (&(destination->access_region)))
{
ErrorF (" solid not in vmem\n");
@@ -444,6 +465,8 @@ Bool
qxl_surface_prepare_copy (qxl_surface_t *dest,
qxl_surface_t *source)
{
+ if (dest->dri2_sw_rendered || source->dri2_sw_rendered)
+ return FALSE;
if (!REGION_NIL (&(dest->access_region)) ||
!REGION_NIL (&(source->access_region)))
{
@@ -604,6 +627,14 @@ qxl_surface_prepare_composite (int op,
qxl_surface_t * mask,
qxl_surface_t * dest)
{
+
+ if (dest->dri2_sw_rendered)
+ return FALSE;
+ if (src && src->dri2_sw_rendered)
+ return FALSE;
+ if (mask && mask->dri2_sw_rendered)
+ return FALSE;
+
dest->u.composite.op = op;
dest->u.composite.src_picture = src_picture;
dest->u.composite.mask_picture = mask_picture;
@@ -806,6 +837,8 @@ qxl_surface_put_image (qxl_surface_t *dest,
struct QXLRect rect;
struct qxl_bo *image_bo;
+ if (dest->dri2_sw_rendered)
+ return FALSE;
rect.left = x;
rect.right = x + width;
rect.top = y;
@@ -869,3 +902,33 @@ qxl_get_formats (int bpp, SpiceBitmapFmt *format, pixman_format_code_t *pformat)
break;
}
}
+
+void
+qxl_flip_surface(struct qxl_surface_t *surf)
+{
+ int width, height;
+ pixman_image_t *temp;
+ void *dev_addr;
+ pixman_format_code_t format;
+
+ width = pixman_image_get_width (surf->host_image);
+ height = pixman_image_get_height (surf->host_image);
+ format = pixman_image_get_format (surf->host_image);
+ /* flip this surface up the right way */
+ qxl_download_box(surf, 0, 0, width, height);
+
+ dev_addr = surf->qxl->bo_funcs->bo_map(surf->bo);
+ temp = pixman_image_create_bits (format, width, height,
+ (uint32_t *)dev_addr, abs(pixman_image_get_stride(surf->host_image)));
+
+
+ pixman_image_composite (PIXMAN_OP_SRC,
+ surf->host_image,
+ NULL,
+ temp,
+ 0, 0, 0, 0, 0, 0,
+ width, height);
+ pixman_image_unref(temp);
+ surf->qxl->bo_funcs->bo_unmap(surf->bo);
+
+}
diff --git a/src/qxl_surface.h b/src/qxl_surface.h
index 2188098..213a04e 100644
--- a/src/qxl_surface.h
+++ b/src/qxl_surface.h
@@ -28,6 +28,7 @@ struct qxl_surface_t
PixmapPtr pixmap;
+ Bool dri2_sw_rendered;
struct evacuated_surface_t *evacuated;
union
@@ -51,5 +52,5 @@ struct qxl_surface_t
void qxl_download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2);
void qxl_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2);
-
+void qxl_flip_surface(struct qxl_surface_t *surf);
#endif
diff --git a/src/qxl_surface_ums.c b/src/qxl_surface_ums.c
index f6364d1..7b562a0 100644
--- a/src/qxl_surface_ums.c
+++ b/src/qxl_surface_ums.c
@@ -343,7 +343,7 @@ qxl_surface_cache_create_primary (qxl_screen_t *qxl,
surface->bo = bo;
surface->image_bo = NULL;
surface->is_dri2_surf = FALSE;
-
+ surface->dri2_sw_rendered = FALSE;
REGION_INIT (NULL, &(surface->access_region), (BoxPtr)NULL, 0);
surface->access_type = UXA_ACCESS_RO;