|
|
|
@@ -28,16 +28,13 @@
|
|
|
|
|
#include "intel_screen.h"
|
|
|
|
|
#include "intel_context.h"
|
|
|
|
|
#include "intel_swapbuffers.h"
|
|
|
|
|
|
|
|
|
|
#include "intel_batchbuffer.h"
|
|
|
|
|
#include "intel_reg.h"
|
|
|
|
|
|
|
|
|
|
#include "pipe/p_context.h"
|
|
|
|
|
#include "state_tracker/st_public.h"
|
|
|
|
|
#include "state_tracker/st_context.h"
|
|
|
|
|
#include "state_tracker/st_cb_fbo.h"
|
|
|
|
|
|
|
|
|
|
#include "intel_drm/ws_dri_bufmgr.h"
|
|
|
|
|
#include "intel_batchbuffer.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Display a colorbuffer surface in an X window.
|
|
|
|
@@ -49,158 +46,130 @@
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
intelDisplaySurface(__DRIdrawablePrivate *dPriv,
|
|
|
|
|
struct pipe_surface *surf,
|
|
|
|
|
const drm_clip_rect_t *rect)
|
|
|
|
|
struct pipe_texture *tex,
|
|
|
|
|
const drm_clip_rect_t *rect)
|
|
|
|
|
{
|
|
|
|
|
struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
|
|
|
|
|
struct intel_context *intel = intelScreen->dummyContext;
|
|
|
|
|
struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
|
|
|
|
|
struct intel_context *intel = intelScreen->dummyContext;
|
|
|
|
|
|
|
|
|
|
DBG(SWAP, "%s\n", __FUNCTION__);
|
|
|
|
|
DBG(SWAP, "%s\n", __FUNCTION__);
|
|
|
|
|
|
|
|
|
|
if (!intel) {
|
|
|
|
|
/* XXX this is where some kind of extra/meta context could be useful */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!intel) {
|
|
|
|
|
/* XXX this is where some kind of extra/meta context could be useful */
|
|
|
|
|
return;
|
|
|
|
|
} else if (!intel->blit) {
|
|
|
|
|
intel->blit = util_create_blit(intel->st->pipe, intel->st->cso_context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (intel->last_swap_fence) {
|
|
|
|
|
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
|
|
|
|
|
driFenceUnReference(&intel->last_swap_fence);
|
|
|
|
|
intel->last_swap_fence = NULL;
|
|
|
|
|
}
|
|
|
|
|
intel->last_swap_fence = intel->first_swap_fence;
|
|
|
|
|
intel->first_swap_fence = NULL;
|
|
|
|
|
if (intel->last_swap_fence) {
|
|
|
|
|
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
|
|
|
|
|
driFenceUnReference(&intel->last_swap_fence);
|
|
|
|
|
intel->last_swap_fence = NULL;
|
|
|
|
|
}
|
|
|
|
|
intel->last_swap_fence = intel->first_swap_fence;
|
|
|
|
|
intel->first_swap_fence = NULL;
|
|
|
|
|
|
|
|
|
|
/* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
|
|
|
|
|
* should work regardless.
|
|
|
|
|
*/
|
|
|
|
|
LOCK_HARDWARE(intel);
|
|
|
|
|
/* if this drawable isn't currently bound the LOCK_HARDWARE done on the
|
|
|
|
|
* current context (which is what intelScreenContext should return) might
|
|
|
|
|
* not get a contended lock and thus cliprects not updated (tests/manywin)
|
|
|
|
|
*/
|
|
|
|
|
if (intel_context(dPriv->driContextPriv) != intel)
|
|
|
|
|
DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv);
|
|
|
|
|
/* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
|
|
|
|
|
* should work regardless.
|
|
|
|
|
*/
|
|
|
|
|
LOCK_HARDWARE(intel);
|
|
|
|
|
/* if this drawable isn't currently bound the LOCK_HARDWARE done on the
|
|
|
|
|
* current context (which is what intelScreenContext should return) might
|
|
|
|
|
* not get a contended lock and thus cliprects not updated (tests/manywin)
|
|
|
|
|
*/
|
|
|
|
|
if (intel_context(dPriv->driContextPriv) != intel)
|
|
|
|
|
DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv);
|
|
|
|
|
|
|
|
|
|
if (dPriv && dPriv->numClipRects) {
|
|
|
|
|
const int srcWidth = tex->width[0];
|
|
|
|
|
const int srcHeight = tex->height[0];
|
|
|
|
|
const int nbox = dPriv->numClipRects;
|
|
|
|
|
const drm_clip_rect_t *pbox = dPriv->pClipRects;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert(surf->buffer);
|
|
|
|
|
assert(surf->cpp == cpp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dPriv && dPriv->numClipRects) {
|
|
|
|
|
const int srcWidth = surf->width;
|
|
|
|
|
const int srcHeight = surf->height;
|
|
|
|
|
const int nbox = dPriv->numClipRects;
|
|
|
|
|
const drm_clip_rect_t *pbox = dPriv->pClipRects;
|
|
|
|
|
const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
|
|
|
|
|
const int cpp = intelScreen->front.cpp;
|
|
|
|
|
const int srcpitch = surf->stride / cpp;
|
|
|
|
|
int BR13, CMD;
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < nbox; i++, pbox++) {
|
|
|
|
|
drm_clip_rect_t box;
|
|
|
|
|
drm_clip_rect_t sbox;
|
|
|
|
|
|
|
|
|
|
ASSERT(surf->buffer);
|
|
|
|
|
ASSERT(surf->cpp == cpp);
|
|
|
|
|
if (pbox->x1 > pbox->x2 ||
|
|
|
|
|
pbox->y1 > pbox->y2 ||
|
|
|
|
|
pbox->x2 > intelScreen->front.width ||
|
|
|
|
|
pbox->y2 > intelScreen->front.height) {
|
|
|
|
|
/* invalid cliprect, skip it */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG(SWAP, "screen pitch %d src surface pitch %d\n",
|
|
|
|
|
pitch, surf->stride);
|
|
|
|
|
box = *pbox;
|
|
|
|
|
|
|
|
|
|
if (cpp == 2) {
|
|
|
|
|
BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
|
|
|
|
|
CMD = XY_SRC_COPY_BLT_CMD;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
|
|
|
|
|
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
|
|
|
|
|
XY_SRC_COPY_BLT_WRITE_RGB);
|
|
|
|
|
}
|
|
|
|
|
if (rect) {
|
|
|
|
|
/* intersect cliprect with user-provided src rect */
|
|
|
|
|
drm_clip_rect_t rrect;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nbox; i++, pbox++) {
|
|
|
|
|
drm_clip_rect_t box;
|
|
|
|
|
drm_clip_rect_t sbox;
|
|
|
|
|
rrect.x1 = dPriv->x + rect->x1;
|
|
|
|
|
rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y;
|
|
|
|
|
rrect.x2 = rect->x2 + rrect.x1;
|
|
|
|
|
rrect.y2 = rect->y2 + rrect.y1;
|
|
|
|
|
if (rrect.x1 > box.x1)
|
|
|
|
|
box.x1 = rrect.x1;
|
|
|
|
|
if (rrect.y1 > box.y1)
|
|
|
|
|
box.y1 = rrect.y1;
|
|
|
|
|
if (rrect.x2 < box.x2)
|
|
|
|
|
box.x2 = rrect.x2;
|
|
|
|
|
if (rrect.y2 < box.y2)
|
|
|
|
|
box.y2 = rrect.y2;
|
|
|
|
|
|
|
|
|
|
if (pbox->x1 > pbox->x2 ||
|
|
|
|
|
pbox->y1 > pbox->y2 ||
|
|
|
|
|
pbox->x2 > intelScreen->front.width ||
|
|
|
|
|
pbox->y2 > intelScreen->front.height) {
|
|
|
|
|
/* invalid cliprect, skip it */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (box.x1 > box.x2 || box.y1 > box.y2)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
box = *pbox;
|
|
|
|
|
/* restrict blit to size of actually rendered area */
|
|
|
|
|
if (box.x2 - box.x1 > srcWidth)
|
|
|
|
|
box.x2 = srcWidth + box.x1;
|
|
|
|
|
if (box.y2 - box.y1 > srcHeight)
|
|
|
|
|
box.y2 = srcHeight + box.y1;
|
|
|
|
|
|
|
|
|
|
if (rect) {
|
|
|
|
|
/* intersect cliprect with user-provided src rect */
|
|
|
|
|
drm_clip_rect_t rrect;
|
|
|
|
|
DBG(SWAP, "\tdbox x1 x2 y1 y2 %d %d %d %d\n",
|
|
|
|
|
box.x1, box.x2, box.y1, box.y2);
|
|
|
|
|
|
|
|
|
|
rrect.x1 = dPriv->x + rect->x1;
|
|
|
|
|
rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y;
|
|
|
|
|
rrect.x2 = rect->x2 + rrect.x1;
|
|
|
|
|
rrect.y2 = rect->y2 + rrect.y1;
|
|
|
|
|
if (rrect.x1 > box.x1)
|
|
|
|
|
box.x1 = rrect.x1;
|
|
|
|
|
if (rrect.y1 > box.y1)
|
|
|
|
|
box.y1 = rrect.y1;
|
|
|
|
|
if (rrect.x2 < box.x2)
|
|
|
|
|
box.x2 = rrect.x2;
|
|
|
|
|
if (rrect.y2 < box.y2)
|
|
|
|
|
box.y2 = rrect.y2;
|
|
|
|
|
sbox.x1 = box.x1 - dPriv->x;
|
|
|
|
|
sbox.y1 = box.y1 - dPriv->y;
|
|
|
|
|
sbox.x2 = box.x2 - dPriv->x;
|
|
|
|
|
sbox.y2 = box.y2 - dPriv->y;
|
|
|
|
|
DBG(SWAP, "\tsbox x1 x2 y1 y2 %d %d %d %d\n",
|
|
|
|
|
sbox.x1, sbox.x2, sbox.y1, sbox.y2);
|
|
|
|
|
|
|
|
|
|
if (box.x1 > box.x2 || box.y1 > box.y2)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
assert(box.x1 < box.x2);
|
|
|
|
|
assert(box.y1 < box.y2);
|
|
|
|
|
|
|
|
|
|
/* restrict blit to size of actually rendered area */
|
|
|
|
|
if (box.x2 - box.x1 > srcWidth)
|
|
|
|
|
box.x2 = srcWidth + box.x1;
|
|
|
|
|
if (box.y2 - box.y1 > srcHeight)
|
|
|
|
|
box.y2 = srcHeight + box.y1;
|
|
|
|
|
util_blit_pixels_tex(intel->blit,
|
|
|
|
|
tex,
|
|
|
|
|
sbox.x1, sbox.y1,
|
|
|
|
|
sbox.x2, sbox.y2,
|
|
|
|
|
intelScreen->front.surface,
|
|
|
|
|
box.x1, box.y1,
|
|
|
|
|
box.x2, box.y2,
|
|
|
|
|
0.0,
|
|
|
|
|
PIPE_TEX_MIPFILTER_NEAREST);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n",
|
|
|
|
|
box.x1, box.x2, box.y1, box.y2);
|
|
|
|
|
if (intel->first_swap_fence)
|
|
|
|
|
driFenceUnReference(&intel->first_swap_fence);
|
|
|
|
|
intel->first_swap_fence = intel_be_batchbuffer_flush(intel->base.batch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sbox.x1 = box.x1 - dPriv->x;
|
|
|
|
|
sbox.y1 = box.y1 - dPriv->y;
|
|
|
|
|
|
|
|
|
|
assert(box.x1 < box.x2);
|
|
|
|
|
assert(box.y1 < box.y2);
|
|
|
|
|
UNLOCK_HARDWARE(intel);
|
|
|
|
|
|
|
|
|
|
/* XXX this could be done with pipe->surface_copy() */
|
|
|
|
|
/* XXX should have its own batch buffer */
|
|
|
|
|
if (!BEGIN_BATCH(8, 2)) {
|
|
|
|
|
/*
|
|
|
|
|
* Since we share this batch buffer with a context
|
|
|
|
|
* we can't flush it since that risks a GPU lockup
|
|
|
|
|
*/
|
|
|
|
|
assert(0);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OUT_BATCH(CMD);
|
|
|
|
|
OUT_BATCH(BR13);
|
|
|
|
|
OUT_BATCH((box.y1 << 16) | box.x1);
|
|
|
|
|
OUT_BATCH((box.y2 << 16) | box.x2);
|
|
|
|
|
|
|
|
|
|
OUT_RELOC(intelScreen->front.buffer,
|
|
|
|
|
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
|
|
|
|
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
|
|
|
|
|
OUT_BATCH((sbox.y1 << 16) | sbox.x1);
|
|
|
|
|
OUT_BATCH((srcpitch * cpp) & 0xffff);
|
|
|
|
|
OUT_RELOC(dri_bo(surf->buffer),
|
|
|
|
|
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
|
|
|
|
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (intel->first_swap_fence)
|
|
|
|
|
driFenceUnReference(&intel->first_swap_fence);
|
|
|
|
|
intel->first_swap_fence = intel_be_batchbuffer_flush(intel->base.batch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UNLOCK_HARDWARE(intel);
|
|
|
|
|
|
|
|
|
|
if (intel->lastStamp != dPriv->lastStamp) {
|
|
|
|
|
intelUpdateWindowSize(dPriv);
|
|
|
|
|
intel->lastStamp = dPriv->lastStamp;
|
|
|
|
|
}
|
|
|
|
|
if (intel->lastStamp != dPriv->lastStamp) {
|
|
|
|
|
intelUpdateWindowSize(dPriv);
|
|
|
|
|
intel->lastStamp = dPriv->lastStamp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This will be called whenever the currently bound window is moved/resized.
|
|
|
|
|
*/
|
|
|
|
@@ -212,27 +181,27 @@ intelUpdateWindowSize(__DRIdrawablePrivate *dPriv)
|
|
|
|
|
st_resize_framebuffer(intelfb->stfb, dPriv->w, dPriv->h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called from glx code
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
intelSwapBuffers(__DRIdrawablePrivate * dPriv)
|
|
|
|
|
{
|
|
|
|
|
struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
|
|
|
|
|
struct pipe_surface *back_surf;
|
|
|
|
|
struct pipe_texture *back_tex;
|
|
|
|
|
|
|
|
|
|
assert(intel_fb);
|
|
|
|
|
assert(intel_fb->stfb);
|
|
|
|
|
|
|
|
|
|
back_surf = st_get_framebuffer_surface(intel_fb->stfb,
|
|
|
|
|
ST_SURFACE_BACK_LEFT);
|
|
|
|
|
if (back_surf) {
|
|
|
|
|
back_tex = st_get_framebuffer_texture(intel_fb->stfb,
|
|
|
|
|
ST_SURFACE_BACK_LEFT);
|
|
|
|
|
if (back_tex) {
|
|
|
|
|
st_notify_swapbuffers(intel_fb->stfb);
|
|
|
|
|
intelDisplaySurface(dPriv, back_surf, NULL);
|
|
|
|
|
intelDisplaySurface(dPriv, back_tex, NULL);
|
|
|
|
|
st_notify_swapbuffers_complete(intel_fb->stfb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called via glXCopySubBufferMESA() to copy a subrect of the back
|
|
|
|
|
* buffer to the front buffer/screen.
|
|
|
|
@@ -241,14 +210,14 @@ void
|
|
|
|
|
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
|
|
|
|
|
{
|
|
|
|
|
struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
|
|
|
|
|
struct pipe_surface *back_surf;
|
|
|
|
|
struct pipe_texture *back_tex;
|
|
|
|
|
|
|
|
|
|
assert(intel_fb);
|
|
|
|
|
assert(intel_fb->stfb);
|
|
|
|
|
|
|
|
|
|
back_surf = st_get_framebuffer_surface(intel_fb->stfb,
|
|
|
|
|
ST_SURFACE_BACK_LEFT);
|
|
|
|
|
if (back_surf) {
|
|
|
|
|
back_tex = st_get_framebuffer_texture(intel_fb->stfb,
|
|
|
|
|
ST_SURFACE_BACK_LEFT);
|
|
|
|
|
if (back_tex) {
|
|
|
|
|
drm_clip_rect_t rect;
|
|
|
|
|
rect.x1 = x;
|
|
|
|
|
rect.y1 = y;
|
|
|
|
@@ -256,6 +225,6 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
|
|
|
|
|
rect.y2 = h;
|
|
|
|
|
|
|
|
|
|
st_notify_swapbuffers(intel_fb->stfb);
|
|
|
|
|
intelDisplaySurface(dPriv, back_surf, &rect);
|
|
|
|
|
intelDisplaySurface(dPriv, back_tex, &rect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|