diff options
author | Dave Airlie <airlied@redhat.com> | 2013-03-20 12:47:12 +1000 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2013-03-20 17:25:44 +1000 |
commit | 6bc49646f114a13dd47a71dc68f0d079ad791a32 (patch) | |
tree | 311859c7047f4ac907dc748c61aac129f11e3c2d | |
parent | a0ba7a0b25dfdccb049f6b61342e78f73f2cb70a (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.c | 13 | ||||
-rw-r--r-- | src/qxl_kms.c | 1 | ||||
-rw-r--r-- | src/qxl_surface.c | 63 | ||||
-rw-r--r-- | src/qxl_surface.h | 3 | ||||
-rw-r--r-- | src/qxl_surface_ums.c | 2 |
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; |