1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "intel_screen.h"
29 #include "intel_context.h"
30 #include "intel_swapbuffers.h"
32 #include "intel_reg.h"
34 #include "pipe/p_context.h"
35 #include "state_tracker/st_public.h"
36 #include "state_tracker/st_context.h"
37 #include "state_tracker/st_cb_fbo.h"
39 #include "ws_dri_bufmgr.h"
40 #include "intel_batchbuffer.h"
43 * Display a colorbuffer surface in an X window.
44 * Used for SwapBuffers and flushing front buffer rendering.
46 * \param dPriv the window/drawable to display into
47 * \param surf the surface to display
48 * \param rect optional subrect of surface to display (may be NULL).
51 intelDisplaySurface(__DRIdrawablePrivate
*dPriv
,
52 struct pipe_surface
*surf
,
53 const drm_clip_rect_t
*rect
)
55 struct intel_screen
*intelScreen
= intel_screen(dPriv
->driScreenPriv
);
56 struct intel_context
*intel
= intelScreen
->dummyContext
;
58 DBG(SWAP
, "%s\n", __FUNCTION__
);
61 /* XXX this is where some kind of extra/meta context could be useful */
65 if (intel
->last_swap_fence
) {
66 driFenceFinish(intel
->last_swap_fence
, DRM_FENCE_TYPE_EXE
, TRUE
);
67 driFenceUnReference(&intel
->last_swap_fence
);
68 intel
->last_swap_fence
= NULL
;
70 intel
->last_swap_fence
= intel
->first_swap_fence
;
71 intel
->first_swap_fence
= NULL
;
73 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
74 * should work regardless.
77 /* if this drawable isn't currently bound the LOCK_HARDWARE done on the
78 * current context (which is what intelScreenContext should return) might
79 * not get a contended lock and thus cliprects not updated (tests/manywin)
81 if (intel_context(dPriv
->driContextPriv
) != intel
)
82 DRI_VALIDATE_DRAWABLE_INFO(intel
->driScreen
, dPriv
);
85 if (dPriv
&& dPriv
->numClipRects
) {
86 const int srcWidth
= surf
->width
;
87 const int srcHeight
= surf
->height
;
88 const int nbox
= dPriv
->numClipRects
;
89 const drm_clip_rect_t
*pbox
= dPriv
->pClipRects
;
90 const int pitch
= intelScreen
->front
.pitch
/ intelScreen
->front
.cpp
;
91 const int cpp
= intelScreen
->front
.cpp
;
92 const int srcpitch
= surf
->stride
/ cpp
;
98 DBG(SWAP
, "screen pitch %d src surface pitch %d\n",
102 BR13
= (pitch
* cpp
) | (0xCC << 16) | (1 << 24);
103 CMD
= XY_SRC_COPY_BLT_CMD
;
106 BR13
= (pitch
* cpp
) | (0xCC << 16) | (1 << 24) | (1 << 25);
107 CMD
= (XY_SRC_COPY_BLT_CMD
| XY_SRC_COPY_BLT_WRITE_ALPHA
|
108 XY_SRC_COPY_BLT_WRITE_RGB
);
111 for (i
= 0; i
< nbox
; i
++, pbox
++) {
113 drm_clip_rect_t sbox
;
115 if (pbox
->x1
> pbox
->x2
||
116 pbox
->y1
> pbox
->y2
||
117 pbox
->x2
> intelScreen
->front
.width
||
118 pbox
->y2
> intelScreen
->front
.height
) {
119 /* invalid cliprect, skip it */
126 /* intersect cliprect with user-provided src rect */
127 drm_clip_rect_t rrect
;
129 rrect
.x1
= dPriv
->x
+ rect
->x1
;
130 rrect
.y1
= (dPriv
->h
- rect
->y1
- rect
->y2
) + dPriv
->y
;
131 rrect
.x2
= rect
->x2
+ rrect
.x1
;
132 rrect
.y2
= rect
->y2
+ rrect
.y1
;
133 if (rrect
.x1
> box
.x1
)
135 if (rrect
.y1
> box
.y1
)
137 if (rrect
.x2
< box
.x2
)
139 if (rrect
.y2
< box
.y2
)
142 if (box
.x1
> box
.x2
|| box
.y1
> box
.y2
)
146 /* restrict blit to size of actually rendered area */
147 if (box
.x2
- box
.x1
> srcWidth
)
148 box
.x2
= srcWidth
+ box
.x1
;
149 if (box
.y2
- box
.y1
> srcHeight
)
150 box
.y2
= srcHeight
+ box
.y1
;
152 DBG(SWAP
, "box x1 x2 y1 y2 %d %d %d %d\n",
153 box
.x1
, box
.x2
, box
.y1
, box
.y2
);
155 sbox
.x1
= box
.x1
- dPriv
->x
;
156 sbox
.y1
= box
.y1
- dPriv
->y
;
158 assert(box
.x1
< box
.x2
);
159 assert(box
.y1
< box
.y2
);
161 /* XXX this could be done with pipe->surface_copy() */
162 /* XXX should have its own batch buffer */
163 if (!BEGIN_BATCH(8, 2)) {
165 * Since we share this batch buffer with a context
166 * we can't flush it since that risks a GPU lockup
174 OUT_BATCH((box
.y1
<< 16) | box
.x1
);
175 OUT_BATCH((box
.y2
<< 16) | box
.x2
);
177 OUT_RELOC(intelScreen
->front
.buffer
,
178 DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
179 DRM_BO_MASK_MEM
| DRM_BO_FLAG_WRITE
, 0);
180 OUT_BATCH((sbox
.y1
<< 16) | sbox
.x1
);
181 OUT_BATCH((srcpitch
* cpp
) & 0xffff);
182 OUT_RELOC(dri_bo(surf
->buffer
),
183 DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_READ
,
184 DRM_BO_MASK_MEM
| DRM_BO_FLAG_READ
, 0);
188 if (intel
->first_swap_fence
)
189 driFenceUnReference(&intel
->first_swap_fence
);
190 intel
->first_swap_fence
= intel_be_batchbuffer_flush(intel
->base
.batch
);
193 UNLOCK_HARDWARE(intel
);
195 if (intel
->lastStamp
!= dPriv
->lastStamp
) {
196 intelUpdateWindowSize(dPriv
);
197 intel
->lastStamp
= dPriv
->lastStamp
;
204 * This will be called whenever the currently bound window is moved/resized.
207 intelUpdateWindowSize(__DRIdrawablePrivate
*dPriv
)
209 struct intel_framebuffer
*intelfb
= intel_framebuffer(dPriv
);
210 assert(intelfb
->stfb
);
211 st_resize_framebuffer(intelfb
->stfb
, dPriv
->w
, dPriv
->h
);
217 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
219 struct intel_framebuffer
*intel_fb
= intel_framebuffer(dPriv
);
220 struct pipe_surface
*back_surf
;
223 assert(intel_fb
->stfb
);
225 back_surf
= st_get_framebuffer_surface(intel_fb
->stfb
,
226 ST_SURFACE_BACK_LEFT
);
228 st_notify_swapbuffers(intel_fb
->stfb
);
229 intelDisplaySurface(dPriv
, back_surf
, NULL
);
230 st_notify_swapbuffers_complete(intel_fb
->stfb
);
236 * Called via glXCopySubBufferMESA() to copy a subrect of the back
237 * buffer to the front buffer/screen.
240 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
242 struct intel_framebuffer
*intel_fb
= intel_framebuffer(dPriv
);
243 struct pipe_surface
*back_surf
;
246 assert(intel_fb
->stfb
);
248 back_surf
= st_get_framebuffer_surface(intel_fb
->stfb
,
249 ST_SURFACE_BACK_LEFT
);
251 drm_clip_rect_t rect
;
257 st_notify_swapbuffers(intel_fb
->stfb
);
258 intelDisplaySurface(dPriv
, back_surf
, &rect
);