intel_swapbuffers.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00028 #include "intel_screen.h"
00029 #include "intel_context.h"
00030 #include "intel_swapbuffers.h"
00031 
00032 #include "intel_reg.h"
00033 
00034 #include "pipe/p_context.h"
00035 #include "state_tracker/st_public.h"
00036 #include "state_tracker/st_context.h"
00037 #include "state_tracker/st_cb_fbo.h"
00038 
00039 #include "ws_dri_bufmgr.h"
00040 #include "intel_batchbuffer.h"
00041 
00050 void
00051 intelDisplaySurface(__DRIdrawablePrivate *dPriv,
00052                     struct pipe_surface *surf,
00053                     const drm_clip_rect_t *rect)
00054 {
00055    struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
00056    struct intel_context *intel = intelScreen->dummyContext;
00057 
00058    DBG(SWAP, "%s\n", __FUNCTION__);
00059 
00060    if (!intel) {
00061       /* XXX this is where some kind of extra/meta context could be useful */
00062       return;
00063    }
00064 
00065    if (intel->last_swap_fence) {
00066       driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
00067       driFenceUnReference(&intel->last_swap_fence);
00068       intel->last_swap_fence = NULL;
00069    }
00070    intel->last_swap_fence = intel->first_swap_fence;
00071    intel->first_swap_fence = NULL;
00072 
00073    /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets
00074     * should work regardless.
00075     */
00076    LOCK_HARDWARE(intel);
00077    /* if this drawable isn't currently bound the LOCK_HARDWARE done on the
00078     * current context (which is what intelScreenContext should return) might
00079     * not get a contended lock and thus cliprects not updated (tests/manywin)
00080     */
00081    if (intel_context(dPriv->driContextPriv) != intel)
00082       DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv);
00083 
00084 
00085    if (dPriv && dPriv->numClipRects) {
00086       const int srcWidth = surf->width;
00087       const int srcHeight = surf->height;
00088       const int nbox = dPriv->numClipRects;
00089       const drm_clip_rect_t *pbox = dPriv->pClipRects;
00090       const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
00091       const int cpp = intelScreen->front.cpp;
00092       const int srcpitch = surf->stride / cpp;
00093       int BR13, CMD;
00094       int i;
00095 
00096       ASSERT(surf->buffer);
00097 
00098       DBG(SWAP, "screen pitch %d  src surface pitch %d\n",
00099           pitch, surf->stride);
00100 
00101       if (cpp == 2) {
00102          BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
00103          CMD = XY_SRC_COPY_BLT_CMD;
00104       }
00105       else {
00106          BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
00107          CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
00108                 XY_SRC_COPY_BLT_WRITE_RGB);
00109       }
00110 
00111       for (i = 0; i < nbox; i++, pbox++) {
00112          drm_clip_rect_t box;
00113          drm_clip_rect_t sbox;
00114 
00115          if (pbox->x1 > pbox->x2 ||
00116              pbox->y1 > pbox->y2 ||
00117              pbox->x2 > intelScreen->front.width ||
00118              pbox->y2 > intelScreen->front.height) {
00119             /* invalid cliprect, skip it */
00120             continue;
00121          }
00122 
00123          box = *pbox;
00124 
00125          if (rect) {
00126             /* intersect cliprect with user-provided src rect */
00127             drm_clip_rect_t rrect;
00128 
00129             rrect.x1 = dPriv->x + rect->x1;
00130             rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y;
00131             rrect.x2 = rect->x2 + rrect.x1;
00132             rrect.y2 = rect->y2 + rrect.y1;
00133             if (rrect.x1 > box.x1)
00134                box.x1 = rrect.x1;
00135             if (rrect.y1 > box.y1)
00136                box.y1 = rrect.y1;
00137             if (rrect.x2 < box.x2)
00138                box.x2 = rrect.x2;
00139             if (rrect.y2 < box.y2)
00140                box.y2 = rrect.y2;
00141 
00142             if (box.x1 > box.x2 || box.y1 > box.y2)
00143                continue;
00144          }
00145 
00146          /* restrict blit to size of actually rendered area */
00147          if (box.x2 - box.x1 > srcWidth)
00148             box.x2 = srcWidth + box.x1;
00149          if (box.y2 - box.y1 > srcHeight)
00150             box.y2 = srcHeight + box.y1;
00151 
00152          DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n",
00153              box.x1, box.x2, box.y1, box.y2);
00154 
00155          sbox.x1 = box.x1 - dPriv->x;
00156          sbox.y1 = box.y1 - dPriv->y;
00157 
00158          assert(box.x1 < box.x2);
00159          assert(box.y1 < box.y2);
00160 
00161          /* XXX this could be done with pipe->surface_copy() */
00162          /* XXX should have its own batch buffer */
00163          if (!BEGIN_BATCH(8, 2)) {
00164             /*
00165              * Since we share this batch buffer with a context
00166              * we can't flush it since that risks a GPU lockup
00167              */
00168             assert(0);
00169             continue;
00170          }
00171 
00172          OUT_BATCH(CMD);
00173          OUT_BATCH(BR13);
00174          OUT_BATCH((box.y1 << 16) | box.x1);
00175          OUT_BATCH((box.y2 << 16) | box.x2);
00176 
00177          OUT_RELOC(intelScreen->front.buffer,
00178                    DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
00179                    DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
00180          OUT_BATCH((sbox.y1 << 16) | sbox.x1);
00181          OUT_BATCH((srcpitch * cpp) & 0xffff);
00182          OUT_RELOC(dri_bo(surf->buffer),
00183                    DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
00184                    DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
00185 
00186       }
00187 
00188       if (intel->first_swap_fence)
00189          driFenceUnReference(&intel->first_swap_fence);
00190       intel->first_swap_fence = intel_be_batchbuffer_flush(intel->base.batch);
00191    }
00192 
00193    UNLOCK_HARDWARE(intel);
00194 
00195    if (intel->lastStamp != dPriv->lastStamp) {
00196       intelUpdateWindowSize(dPriv);
00197       intel->lastStamp = dPriv->lastStamp;
00198    }
00199 }
00200 
00201 
00202 
00206 void
00207 intelUpdateWindowSize(__DRIdrawablePrivate *dPriv)
00208 {
00209    struct intel_framebuffer *intelfb = intel_framebuffer(dPriv);
00210    assert(intelfb->stfb);
00211    st_resize_framebuffer(intelfb->stfb, dPriv->w, dPriv->h);
00212 }
00213 
00214 
00215 
00216 void
00217 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
00218 {
00219    struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
00220    struct pipe_surface *back_surf;
00221 
00222    assert(intel_fb);
00223    assert(intel_fb->stfb);
00224 
00225    back_surf = st_get_framebuffer_surface(intel_fb->stfb,
00226                                           ST_SURFACE_BACK_LEFT);
00227    if (back_surf) {
00228       st_notify_swapbuffers(intel_fb->stfb);
00229       intelDisplaySurface(dPriv, back_surf, NULL);
00230       st_notify_swapbuffers_complete(intel_fb->stfb);
00231    }
00232 }
00233 
00234 
00239 void
00240 intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
00241 {
00242    struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
00243    struct pipe_surface *back_surf;
00244 
00245    assert(intel_fb);
00246    assert(intel_fb->stfb);
00247 
00248    back_surf = st_get_framebuffer_surface(intel_fb->stfb,
00249                                           ST_SURFACE_BACK_LEFT);
00250    if (back_surf) {
00251       drm_clip_rect_t rect;
00252       rect.x1 = x;
00253       rect.y1 = y;
00254       rect.x2 = w;
00255       rect.y2 = h;
00256 
00257       st_notify_swapbuffers(intel_fb->stfb);
00258       intelDisplaySurface(dPriv, back_surf, &rect);
00259    }
00260 }

Generated on Tue Sep 29 06:25:17 2009 for Gallium3D by  doxygen 1.5.4