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"
31 #include "intel_batchbuffer.h"
32 #include "intel_reg.h"
33 #include "intel_winsys.h"
35 #include "pipe/p_context.h"
36 #include "state_tracker/st_public.h"
37 #include "state_tracker/st_context.h"
38 #include "state_tracker/st_cb_fbo.h"
42 * Display a colorbuffer surface in an X window.
43 * Used for SwapBuffers and flushing front buffer rendering.
45 * \param dPriv the window/drawable to display into
46 * \param surf the surface to display
47 * \param rect optional subrect of surface to display (may be NULL).
50 intelDisplaySurface(__DRIdrawablePrivate
*dPriv
,
51 struct pipe_surface
*surf
,
52 const drm_clip_rect_t
*rect
)
54 struct intel_screen
*intelScreen
= intel_screen(dPriv
->driScreenPriv
);
55 struct intel_context
*intel
= intelScreen
->dummyContext
;
57 DBG(SWAP
, "%s\n", __FUNCTION__
);
60 /* XXX this is where some kind of extra/meta context could be useful */
64 if (intel
->last_swap_fence
) {
65 driFenceFinish(intel
->last_swap_fence
, DRM_FENCE_TYPE_EXE
, TRUE
);
66 driFenceUnReference(intel
->last_swap_fence
);
67 intel
->last_swap_fence
= NULL
;
69 intel
->last_swap_fence
= intel
->first_swap_fence
;
70 intel
->first_swap_fence
= NULL
;
72 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
73 * should work regardless.
76 /* if this drawable isn't currently bound the LOCK_HARDWARE done on the
77 * current context (which is what intelScreenContext should return) might
78 * not get a contended lock and thus cliprects not updated (tests/manywin)
80 if (intel_context(dPriv
->driContextPriv
) != intel
)
81 DRI_VALIDATE_DRAWABLE_INFO(intel
->driScreen
, dPriv
);
84 if (dPriv
&& dPriv
->numClipRects
) {
85 const int srcWidth
= surf
->width
;
86 const int srcHeight
= surf
->height
;
87 const int nbox
= dPriv
->numClipRects
;
88 const drm_clip_rect_t
*pbox
= dPriv
->pClipRects
;
89 const int pitch
= intelScreen
->front
.pitch
/ intelScreen
->front
.cpp
;
90 const int cpp
= intelScreen
->front
.cpp
;
91 const int srcpitch
= surf
->pitch
;
96 ASSERT(surf
->cpp
== 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 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
165 OUT_BATCH((box
.y1
<< 16) | box
.x1
);
166 OUT_BATCH((box
.y2
<< 16) | box
.x2
);
168 OUT_RELOC(intelScreen
->front
.buffer
,
169 DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
170 DRM_BO_MASK_MEM
| DRM_BO_FLAG_WRITE
, 0);
171 OUT_BATCH((sbox
.y1
<< 16) | sbox
.x1
);
172 OUT_BATCH((srcpitch
* cpp
) & 0xffff);
173 OUT_RELOC(dri_bo(surf
->buffer
),
174 DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_READ
,
175 DRM_BO_MASK_MEM
| DRM_BO_FLAG_READ
, 0);
180 if (intel
->first_swap_fence
)
181 driFenceUnReference(intel
->first_swap_fence
);
182 intel
->first_swap_fence
= intel_batchbuffer_flush(intel
->batch
);
183 driFenceReference(intel
->first_swap_fence
);
186 UNLOCK_HARDWARE(intel
);
188 if (intel
->lastStamp
!= dPriv
->lastStamp
) {
189 intelUpdateWindowSize(dPriv
);
190 intel
->lastStamp
= dPriv
->lastStamp
;
197 * This will be called whenever the currently bound window is moved/resized.
200 intelUpdateWindowSize(__DRIdrawablePrivate
*dPriv
)
202 struct intel_framebuffer
*intelfb
= intel_framebuffer(dPriv
);
203 assert(intelfb
->stfb
);
204 st_resize_framebuffer(intelfb
->stfb
, dPriv
->w
, dPriv
->h
);
210 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
212 struct intel_framebuffer
*intel_fb
= intel_framebuffer(dPriv
);
213 struct pipe_surface
*back_surf
;
216 assert(intel_fb
->stfb
);
218 back_surf
= st_get_framebuffer_surface(intel_fb
->stfb
,
219 ST_SURFACE_BACK_LEFT
);
221 st_notify_swapbuffers(intel_fb
->stfb
);
222 intelDisplaySurface(dPriv
, back_surf
, NULL
);
228 * Called via glXCopySubBufferMESA() to copy a subrect of the back
229 * buffer to the front buffer/screen.
232 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
234 struct intel_framebuffer
*intel_fb
= intel_framebuffer(dPriv
);
235 struct pipe_surface
*back_surf
;
238 assert(intel_fb
->stfb
);
240 back_surf
= st_get_framebuffer_surface(intel_fb
->stfb
,
241 ST_SURFACE_BACK_LEFT
);
243 drm_clip_rect_t rect
;
249 st_notify_swapbuffers(intel_fb
->stfb
);
250 intelDisplaySurface(dPriv
, back_surf
, &rect
);