Commit cc1b1410 authored by Siarhei Siamashka's avatar Siarhei Siamashka
Browse files

G2D: accelerate CopyArea between different pixmaps in framebuffer



Now source and destination pixmaps don't need to be the same for
using G2D acceleration (as long as both of them are allocated in
the framebuffer). This allows using G2D to copy pixels from DRI2
buffers to the framebuffer on the fallback path (when the window
of an OpenGL ES application is partially overlapped by some other
windows). Though it only works when composite extension is
disabled, for example by adding the following to xorg.conf:

    Section "Extensions"
        Option "Composite" "Disable"
    EndSection

If composite extension is enabled, windows have backing pixmaps, and
we have a longer chain of copies:

   DRI2 buffer -> backing pixmap -> framebuffer

Because backing pixmap is not allocated in a physically contiguous
memory, it can't be copied using G2D yet.
Signed-off-by: default avatarSiarhei Siamashka <siarhei.siamashka@gmail.com>
parent d6fb7388
...@@ -458,3 +458,90 @@ int sunxi_g2d_blit_a8r8g8b8(sunxi_disp_t *disp, ...@@ -458,3 +458,90 @@ int sunxi_g2d_blit_a8r8g8b8(sunxi_disp_t *disp,
return ioctl(disp->fd_g2d, G2D_CMD_BITBLT, &tmp); return ioctl(disp->fd_g2d, G2D_CMD_BITBLT, &tmp);
} }
/*
* G2D counterpart for pixman_blt (function arguments are the same with
* only sunxi_disp_t extra argument added). Supports 16bpp (r5g6b5) and
* 32bpp (a8r8g8b8) formats and also conversion between them.
*
* Can do G2D accelerated blits only if both source and destination
* buffers are inside framebuffer. Returns FALSE (0) otherwise.
*/
int sunxi_g2d_blt(sunxi_disp_t *disp,
uint32_t *src_bits,
uint32_t *dst_bits,
int src_stride,
int dst_stride,
int src_bpp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int w,
int h)
{
g2d_blt tmp;
/*
* Very minimal validation here. We just assume that if the begginging
* of both source and destination images belongs to the framebuffer,
* then these images are entirely residing inside the framebuffer
* without crossing its borders. Any other checks are supposed
* to be done by the caller.
*/
if ((uint8_t *)src_bits < disp->framebuffer_addr ||
(uint8_t *)src_bits >= disp->framebuffer_addr + disp->framebuffer_size ||
(uint8_t *)dst_bits < disp->framebuffer_addr ||
(uint8_t *)dst_bits >= disp->framebuffer_addr + disp->framebuffer_size)
{
return 0;
}
if (w <= 0 || h <= 0)
return 1;
if (disp->fd_g2d < 0)
return 0;
if ((src_bpp != 16 && src_bpp != 32) || (dst_bpp != 16 && dst_bpp != 32))
return 0;
tmp.flag = G2D_BLT_NONE;
tmp.src_image.addr[0] = disp->framebuffer_paddr +
((uint8_t *)src_bits - disp->framebuffer_addr);
tmp.src_rect.x = src_x;
tmp.src_rect.y = src_y;
tmp.src_rect.w = w;
tmp.src_rect.h = h;
tmp.src_image.h = src_y + h;
if (src_bpp == 32) {
tmp.src_image.w = src_stride;
tmp.src_image.format = G2D_FMT_ARGB_AYUV8888;
tmp.src_image.pixel_seq = G2D_SEQ_NORMAL;
}
else if (src_bpp == 16) {
tmp.src_image.w = src_stride * 2;
tmp.src_image.format = G2D_FMT_RGB565;
tmp.src_image.pixel_seq = G2D_SEQ_P10;
}
tmp.dst_image.addr[0] = disp->framebuffer_paddr +
((uint8_t *)dst_bits - disp->framebuffer_addr);
tmp.dst_x = dst_x;
tmp.dst_y = dst_y;
tmp.color = 0;
tmp.alpha = 0;
tmp.dst_image.h = dst_y + h;
if (dst_bpp == 32) {
tmp.dst_image.w = dst_stride;
tmp.dst_image.format = G2D_FMT_ARGB_AYUV8888;
tmp.dst_image.pixel_seq = G2D_SEQ_NORMAL;
}
else if (dst_bpp == 16) {
tmp.dst_image.w = dst_stride * 2;
tmp.dst_image.format = G2D_FMT_RGB565;
tmp.dst_image.pixel_seq = G2D_SEQ_P10;
}
return ioctl(disp->fd_g2d, G2D_CMD_BITBLT, &tmp) == 0;
}
...@@ -113,4 +113,19 @@ int sunxi_g2d_blit_a8r8g8b8(sunxi_disp_t *disp, ...@@ -113,4 +113,19 @@ int sunxi_g2d_blit_a8r8g8b8(sunxi_disp_t *disp,
int w, int w,
int h); int h);
/* G2D counterpart for pixman_blt with the support for 16bpp and 32bpp */
int sunxi_g2d_blt(sunxi_disp_t *disp,
uint32_t *src_bits,
uint32_t *dst_bits,
int src_stride,
int dst_stride,
int src_bpp,
int dst_bpp,
int src_x,
int src_y,
int dst_x,
int dst_y,
int w,
int h);
#endif #endif
...@@ -74,11 +74,12 @@ xCopyWindowProc(DrawablePtr pSrcDrawable, ...@@ -74,11 +74,12 @@ xCopyWindowProc(DrawablePtr pSrcDrawable,
(dy + srcYoff != dstYoff || dx + srcXoff + 1 >= dstXoff)) (dy + srcYoff != dstYoff || dx + srcXoff + 1 >= dstXoff))
{ {
while (nbox--) { while (nbox--) {
sunxi_g2d_blit_a8r8g8b8(disp, sunxi_g2d_blt(disp, (uint32_t *)src, (uint32_t *)dst,
pbox->x1 + dstXoff, pbox->y1 + dstYoff, srcStride, dstStride,
pbox->x1 + dx + srcXoff, pbox->y1 + dy + srcYoff, srcBpp, dstBpp, (pbox->x1 + dx + srcXoff),
pbox->x2 - pbox->x1, (pbox->y1 + dy + srcYoff), (pbox->x1 + dstXoff),
pbox->y2 - pbox->y1); (pbox->y1 + dstYoff), (pbox->x2 - pbox->x1),
(pbox->y2 - pbox->y1));
pbox++; pbox++;
} }
} }
...@@ -155,31 +156,38 @@ xCopyNtoN(DrawablePtr pSrcDrawable, ...@@ -155,31 +156,38 @@ xCopyNtoN(DrawablePtr pSrcDrawable,
ScreenPtr pScreen = pDstDrawable->pScreen; ScreenPtr pScreen = pDstDrawable->pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
sunxi_disp_t *disp = SUNXI_DISP(pScrn); sunxi_disp_t *disp = SUNXI_DISP(pScrn);
Bool use_g2d; Bool bad_overlapping_for_g2d;
fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
use_g2d = disp->framebuffer_addr == (void *)src && bad_overlapping_for_g2d = (src == dst) && (dy + srcYoff == dstYoff) &&
disp->framebuffer_addr == (void *)dst && (dx + srcXoff + 1 < dstXoff);
(dy + srcYoff != dstYoff || dx + srcXoff + 1 >= dstXoff);
while (nbox--) { while (nbox--) {
if (use_g2d) { Bool done = FALSE;
sunxi_g2d_blit_a8r8g8b8(disp,
pbox->x1 + dstXoff, pbox->y1 + dstYoff, /* first try G2D */
pbox->x1 + dx + srcXoff, pbox->y1 + dy + srcYoff, if (!bad_overlapping_for_g2d) {
pbox->x2 - pbox->x1, done = sunxi_g2d_blt(disp, (uint32_t *)src, (uint32_t *)dst,
pbox->y2 - pbox->y1); srcStride, dstStride,
srcBpp, dstBpp, (pbox->x1 + dx + srcXoff),
(pbox->y1 + dy + srcYoff), (pbox->x1 + dstXoff),
(pbox->y1 + dstYoff), (pbox->x2 - pbox->x1),
(pbox->y2 - pbox->y1));
} }
else if (!reverse && !upsidedown) {
pixman_blt((uint32_t *) src, (uint32_t *) dst, srcStride, dstStride, /* then pixman (NEON) */
if (!done && !reverse && !upsidedown) {
done = pixman_blt((uint32_t *)src, (uint32_t *)dst, srcStride, dstStride,
srcBpp, dstBpp, (pbox->x1 + dx + srcXoff), srcBpp, dstBpp, (pbox->x1 + dx + srcXoff),
(pbox->y1 + dy + srcYoff), (pbox->x1 + dstXoff), (pbox->y1 + dy + srcYoff), (pbox->x1 + dstXoff),
(pbox->y1 + dstYoff), (pbox->x2 - pbox->x1), (pbox->y1 + dstYoff), (pbox->x2 - pbox->x1),
(pbox->y2 - pbox->y1)); (pbox->y2 - pbox->y1));
} }
else {
/* fallback to fbBlt if other methods did not work */
if (!done) {
fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride, fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride,
srcStride, srcStride,
(pbox->x1 + dx + srcXoff) * srcBpp, (pbox->x1 + dx + srcXoff) * srcBpp,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment