#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.
*/
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;
-
- DBG(SWAP, "%s\n", __FUNCTION__);
-
- if (!intel) {
- /* XXX this is where some kind of extra/meta context could be useful */
- return;
- }
-
- 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);
-
-
- 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;
-
- ASSERT(surf->buffer);
- ASSERT(surf->cpp == cpp);
-
- DBG(SWAP, "screen pitch %d src surface pitch %d\n",
- pitch, surf->stride);
-
- 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);
- }
-
- for (i = 0; i < nbox; i++, pbox++) {
- drm_clip_rect_t box;
- drm_clip_rect_t sbox;
-
- if (pbox->x1 > pbox->x2 ||
- pbox->y1 > pbox->y2 ||
- pbox->x2 > intelScreen->front.width ||
- pbox->y2 > intelScreen->front.height) {
- /* invalid cliprect, skip it */
- continue;
- }
-
- box = *pbox;
-
- if (rect) {
- /* intersect cliprect with user-provided src rect */
- drm_clip_rect_t rrect;
-
- 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 (box.x1 > box.x2 || box.y1 > box.y2)
- continue;
- }
-
- /* 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;
-
- DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n",
- box.x1, box.x2, box.y1, box.y2);
-
- sbox.x1 = box.x1 - dPriv->x;
- sbox.y1 = box.y1 - dPriv->y;
-
- assert(box.x1 < box.x2);
- assert(box.y1 < box.y2);
-
- /* 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;
- }
+ struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
+ struct intel_context *intel = intelScreen->dummyContext;
+
+ DBG(SWAP, "%s\n", __FUNCTION__);
+
+ 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;
+
+ /* 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);
+
+
+ for (i = 0; i < nbox; i++, pbox++) {
+ drm_clip_rect_t box;
+ drm_clip_rect_t sbox;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > intelScreen->front.width ||
+ pbox->y2 > intelScreen->front.height) {
+ /* invalid cliprect, skip it */
+ continue;
+ }
+
+ box = *pbox;
+
+ if (rect) {
+ /* intersect cliprect with user-provided src rect */
+ drm_clip_rect_t rrect;
+
+ 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 (box.x1 > box.x2 || box.y1 > box.y2)
+ continue;
+ }
+
+ /* 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;
+
+ DBG(SWAP, "\tdbox x1 x2 y1 y2 %d %d %d %d\n",
+ box.x1, box.x2, box.y1, box.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);
+
+ assert(box.x1 < box.x2);
+ assert(box.y1 < box.y2);
+
+ 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);
+ }
+
+ 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;
+ }
}
-
-
/**
* This will be called whenever the currently bound window is moved/resized.
*/
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.
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;
rect.y2 = h;
st_notify_swapbuffers(intel_fb->stfb);
- intelDisplaySurface(dPriv, back_surf, &rect);
+ intelDisplaySurface(dPriv, back_tex, &rect);
}
}