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_blit.h"
31 #include "intel_buffers.h"
32 #include "intel_batchbuffer.h"
33 #include "intel_reg.h"
36 #include "drirenderbuffer.h"
39 #include "pipe/p_context.h"
42 /* This block can be removed when libdrm >= 2.3.1 is required */
44 #ifndef DRM_VBLANK_FLIP
46 #define DRM_VBLANK_FLIP 0x8000000
48 typedef struct drm_i915_flip
{
52 #undef DRM_IOCTL_I915_FLIP
53 #define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
60 * XXX move this into a new dri/common/cliprects.c file.
63 intel_intersect_cliprects(drm_clip_rect_t
* dst
,
64 const drm_clip_rect_t
* a
,
65 const drm_clip_rect_t
* b
)
69 GLint bw
= b
->x2
- bx
;
70 GLint bh
= b
->y2
- by
;
73 bw
-= a
->x1
- bx
, bx
= a
->x1
;
75 bh
-= a
->y1
- by
, by
= a
->y1
;
93 <<<<<<< HEAD
:src
/mesa
/drivers
/dri
/intel_winsys
/intel_buffers
.c
95 * Return pointer to current color drawing region, or NULL.
99 intel_drawbuf_region(struct intel_context
*intel
)
101 struct intel_renderbuffer
*irbColor
=
102 intel_renderbuffer(intel
->ctx
.DrawBuffer
->_ColorDrawBuffers
[0][0]);
104 return irbColor
->Base
.surface
->region
;
109 >>>>>>> remove dead code
, remove intel_fbo
.h includes
:src
/mesa
/drivers
/dri
/intel_winsys
/intel_buffers
.c
111 <<<<<<< HEAD
:src
/mesa
/drivers
/dri
/intel_winsys
/intel_buffers
.c
113 * Return pointer to current color reading region, or NULL.
116 intel_readbuf_region(struct intel_context
*intel
)
118 struct intel_renderbuffer
*irb
119 = intel_renderbuffer(intel
->ctx
.ReadBuffer
->_ColorReadBuffer
);
121 return irb
->Base
.surface
->region
;
127 >>>>>>> remove dead code
, remove intel_fbo
.h includes
:src
/mesa
/drivers
/dri
/intel_winsys
/intel_buffers
.c
130 * This will be called whenever the currently bound window is moved/resized.
131 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
134 intelWindowMoved(struct intel_context
*intel
)
136 GLcontext
*ctx
= &intel
->ctx
;
137 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
138 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
140 if (!intel
->ctx
.DrawBuffer
) {
141 /* when would this happen? -BP */
143 intel
->numClipRects
= 0;
146 /* Update Mesa's notion of window size */
147 driUpdateFramebufferSize(ctx
, dPriv
);
148 intel_fb
->Base
.Initialized
= GL_TRUE
; /* XXX remove someday */
151 drmI830Sarea
*sarea
= intel
->sarea
;
152 drm_clip_rect_t drw_rect
= { .x1
= dPriv
->x
, .x2
= dPriv
->x
+ dPriv
->w
,
153 .y1
= dPriv
->y
, .y2
= dPriv
->y
+ dPriv
->h
};
154 drm_clip_rect_t pipeA_rect
= { .x1
= sarea
->pipeA_x
, .y1
= sarea
->pipeA_y
,
155 .x2
= sarea
->pipeA_x
+ sarea
->pipeA_w
,
156 .y2
= sarea
->pipeA_y
+ sarea
->pipeA_h
};
157 drm_clip_rect_t pipeB_rect
= { .x1
= sarea
->pipeB_x
, .y1
= sarea
->pipeB_y
,
158 .x2
= sarea
->pipeB_x
+ sarea
->pipeB_w
,
159 .y2
= sarea
->pipeB_y
+ sarea
->pipeB_h
};
160 GLint areaA
= driIntersectArea( drw_rect
, pipeA_rect
);
161 GLint areaB
= driIntersectArea( drw_rect
, pipeB_rect
);
162 GLuint flags
= intel_fb
->vblank_flags
;
166 /* Update page flipping info
176 intel_fb
->pf_current_page
= (intel
->sarea
->pf_current_page
>>
177 (intel_fb
->pf_pipes
& 0x2)) & 0x3;
179 intel_fb
->pf_num_pages
= 2 /*intel->intelScreen->third.handle ? 3 : 2*/;
181 pf_active
= pf_pipes
&& (pf_pipes
& intel
->sarea
->pf_active
) == pf_pipes
;
183 if (INTEL_DEBUG
& DEBUG_LOCK
)
184 if (pf_active
!= intel_fb
->pf_active
)
185 _mesa_printf("%s - Page flipping %sactive\n", __progname
,
186 pf_active
? "" : "in");
189 /* Sync pages between pipes if we're flipping on both at the same time */
190 if (pf_pipes
== 0x3 && pf_pipes
!= intel_fb
->pf_pipes
&&
191 (intel
->sarea
->pf_current_page
& 0x3) !=
192 (((intel
->sarea
->pf_current_page
) >> 2) & 0x3)) {
193 drm_i915_flip_t flip
;
195 if (intel_fb
->pf_current_page
==
196 (intel
->sarea
->pf_current_page
& 0x3)) {
197 /* XXX: This is ugly, but emitting two flips 'in a row' can cause
198 * lockups for unknown reasons.
200 intel
->sarea
->pf_current_page
=
201 intel
->sarea
->pf_current_page
& 0x3;
202 intel
->sarea
->pf_current_page
|=
203 ((intel_fb
->pf_current_page
+ intel_fb
->pf_num_pages
- 1) %
204 intel_fb
->pf_num_pages
) << 2;
208 intel
->sarea
->pf_current_page
=
209 intel
->sarea
->pf_current_page
& (0x3 << 2);
210 intel
->sarea
->pf_current_page
|=
211 (intel_fb
->pf_current_page
+ intel_fb
->pf_num_pages
- 1) %
212 intel_fb
->pf_num_pages
;
217 drmCommandWrite(intel
->driFd
, DRM_I915_FLIP
, &flip
, sizeof(flip
));
220 intel_fb
->pf_pipes
= pf_pipes
;
223 intel_fb
->pf_active
= pf_active
;
225 intel_flip_renderbuffers(intel_fb
);
226 intel_draw_buffer(&intel
->ctx
, intel
->ctx
.DrawBuffer
);
229 /* Update vblank info
231 if (areaB
> areaA
|| (areaA
== areaB
&& areaB
> 0)) {
232 flags
= intel_fb
->vblank_flags
| VBLANK_FLAG_SECONDARY
;
234 flags
= intel_fb
->vblank_flags
& ~VBLANK_FLAG_SECONDARY
;
237 if (flags
!= intel_fb
->vblank_flags
&& intel_fb
->vblank_flags
&&
238 !(intel_fb
->vblank_flags
& VBLANK_FLAG_NO_IRQ
)) {
242 vbl
.request
.type
= DRM_VBLANK_ABSOLUTE
;
244 if ( intel_fb
->vblank_flags
& VBLANK_FLAG_SECONDARY
) {
245 vbl
.request
.type
|= DRM_VBLANK_SECONDARY
;
248 for (i
= 0; i
< intel_fb
->pf_num_pages
; i
++) {
249 if ((intel_fb
->vbl_waited
- intel_fb
->vbl_pending
[i
]) <= (1<<23))
252 vbl
.request
.sequence
= intel_fb
->vbl_pending
[i
];
253 drmWaitVBlank(intel
->driFd
, &vbl
);
256 intel_fb
->vblank_flags
= flags
;
257 driGetCurrentVBlank(dPriv
, intel_fb
->vblank_flags
, &intel_fb
->vbl_seq
);
258 intel_fb
->vbl_waited
= intel_fb
->vbl_seq
;
260 for (i
= 0; i
< intel_fb
->pf_num_pages
; i
++) {
261 intel_fb
->vbl_pending
[i
] = intel_fb
->vbl_waited
;
266 /* This will be picked up by looking at the dirty state flags:
269 /* Update hardware scissor */
270 // ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
271 // ctx->Scissor.Width, ctx->Scissor.Height);
273 /* Re-calculate viewport related state */
274 // ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
281 /* Emit wait for pending flips */
284 intel_wait_flips(struct intel_context
*intel
, GLuint batch_flags
)
286 struct intel_framebuffer
*intel_fb
=
287 (struct intel_framebuffer
*) intel
->ctx
.DrawBuffer
;
288 struct intel_renderbuffer
*intel_rb
=
289 intel_get_renderbuffer(&intel_fb
->Base
,
290 intel_fb
->Base
._ColorDrawBufferMask
[0] ==
291 BUFFER_BIT_FRONT_LEFT
? BUFFER_FRONT_LEFT
:
294 if (intel_fb
->Base
.Name
== 0 && intel_rb
->pf_pending
== intel_fb
->pf_seq
) {
295 GLint pf_pipes
= intel_fb
->pf_pipes
;
298 /* Wait for pending flips to take effect */
299 BEGIN_BATCH(2, batch_flags
);
300 OUT_BATCH(pf_pipes
& 0x1 ? (MI_WAIT_FOR_EVENT
| MI_WAIT_FOR_PLANE_A_FLIP
)
302 OUT_BATCH(pf_pipes
& 0x2 ? (MI_WAIT_FOR_EVENT
| MI_WAIT_FOR_PLANE_B_FLIP
)
306 intel_rb
->pf_pending
--;
312 /* Flip the front & back buffers
315 intelPageFlip(const __DRIdrawablePrivate
* dPriv
)
317 struct intel_context
*intel
;
319 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
321 if (INTEL_DEBUG
& DEBUG_IOCTL
)
322 fprintf(stderr
, "%s\n", __FUNCTION__
);
325 assert(dPriv
->driContextPriv
);
326 assert(dPriv
->driContextPriv
->driverPrivate
);
328 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
330 if (intel
->intelScreen
->drmMinor
< 9)
333 intelFlush(&intel
->ctx
);
337 LOCK_HARDWARE(intel
);
339 if (dPriv
->numClipRects
&& intel_fb
->pf_active
) {
340 drm_i915_flip_t flip
;
342 flip
.pipes
= intel_fb
->pf_pipes
;
344 ret
= drmCommandWrite(intel
->driFd
, DRM_I915_FLIP
, &flip
, sizeof(flip
));
347 UNLOCK_HARDWARE(intel
);
349 if (ret
|| !intel_fb
->pf_active
)
352 if (!dPriv
->numClipRects
) {
353 usleep(10000); /* throttle invisible client 10ms */
356 intel_fb
->pf_current_page
= (intel
->sarea
->pf_current_page
>>
357 (intel_fb
->pf_pipes
& 0x2)) & 0x3;
359 if (dPriv
->numClipRects
!= 0) {
360 intel_get_renderbuffer(&intel_fb
->Base
, BUFFER_FRONT_LEFT
)->pf_pending
=
361 intel_get_renderbuffer(&intel_fb
->Base
, BUFFER_BACK_LEFT
)->pf_pending
=
366 intel_flip_renderbuffers(intel_fb
);
367 intel_draw_buffer(&intel
->ctx
, &intel_fb
->Base
);
370 if (INTEL_DEBUG
& DEBUG_IOCTL
)
371 fprintf(stderr
, "%s: success\n", __FUNCTION__
);
379 intelScheduleSwap(const __DRIdrawablePrivate
* dPriv
, GLboolean
*missed_target
)
381 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
382 unsigned int interval
= driGetVBlankInterval(dPriv
, intel_fb
->vblank_flags
);
383 struct intel_context
*intel
=
384 intelScreenContext(dPriv
->driScreenPriv
->private);
385 const intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
387 drm_i915_vblank_swap_t swap
;
390 if (!intel_fb
->vblank_flags
||
391 (intel_fb
->vblank_flags
& VBLANK_FLAG_NO_IRQ
) ||
392 intelScreen
->drmMinor
< (intel_fb
->pf_active
? 9 : 6))
395 swap
.seqtype
= DRM_VBLANK_ABSOLUTE
;
397 if (intel_fb
->vblank_flags
& VBLANK_FLAG_SYNC
) {
398 swap
.seqtype
|= DRM_VBLANK_NEXTONMISS
;
399 } else if (interval
== 0) {
403 swap
.drawable
= dPriv
->hHWDrawable
;
404 target
= swap
.sequence
= intel_fb
->vbl_seq
+ interval
;
406 if ( intel_fb
->vblank_flags
& VBLANK_FLAG_SECONDARY
) {
407 swap
.seqtype
|= DRM_VBLANK_SECONDARY
;
410 LOCK_HARDWARE(intel
);
412 intel_batchbuffer_flush(intel
->batch
);
414 if ( intel_fb
->pf_active
) {
415 swap
.seqtype
|= DRM_VBLANK_FLIP
;
417 intel_fb
->pf_current_page
= (((intel
->sarea
->pf_current_page
>>
418 (intel_fb
->pf_pipes
& 0x2)) & 0x3) + 1) %
419 intel_fb
->pf_num_pages
;
422 if (!drmCommandWriteRead(intel
->driFd
, DRM_I915_VBLANK_SWAP
, &swap
,
424 intel_fb
->vbl_seq
= swap
.sequence
;
425 swap
.sequence
-= target
;
426 *missed_target
= swap
.sequence
> 0 && swap
.sequence
<= (1 << 23);
429 intel_fb
->vbl_pending
[1] = intel_fb
->vbl_pending
[0] = intel_fb
->vbl_seq
;
431 intel_get_renderbuffer(&intel_fb
->Base
, BUFFER_BACK_LEFT
)->vbl_pending
=
432 intel_get_renderbuffer(&intel_fb
->Base
,
433 BUFFER_FRONT_LEFT
)->vbl_pending
=
437 if (swap
.seqtype
& DRM_VBLANK_FLIP
) {
439 intel_flip_renderbuffers(intel_fb
);
440 intel_draw_buffer(&intel
->ctx
, intel
->ctx
.DrawBuffer
);
446 if (swap
.seqtype
& DRM_VBLANK_FLIP
) {
447 intel_fb
->pf_current_page
= ((intel
->sarea
->pf_current_page
>>
448 (intel_fb
->pf_pipes
& 0x2)) & 0x3) %
449 intel_fb
->pf_num_pages
;
455 UNLOCK_HARDWARE(intel
);
461 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
463 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
464 GET_CURRENT_CONTEXT(ctx
);
465 struct intel_context
*intel
;
470 intel
= intel_context(ctx
);
472 if (ctx
->Visual
.doubleBufferMode
) {
473 GLboolean missed_target
;
474 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
477 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
479 if (!intelScheduleSwap(dPriv
, &missed_target
)) {
480 driWaitForVBlank(dPriv
, &intel_fb
->vbl_seq
, intel_fb
->vblank_flags
,
483 intelCopyBuffer(dPriv
, NULL
);
486 intel_fb
->swap_count
++;
487 (*dri_interface
->getUST
) (&ust
);
489 intel_fb
->swap_missed_count
++;
490 intel_fb
->swap_missed_ust
= ust
- intel_fb
->swap_ust
;
493 intel_fb
->swap_ust
= ust
;
497 /* XXX this shouldn't be an error but we can't handle it for now */
498 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
503 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
505 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
506 struct intel_context
*intel
=
507 (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
508 GLcontext
*ctx
= &intel
->ctx
;
510 if (ctx
->Visual
.doubleBufferMode
) {
511 drm_clip_rect_t rect
;
512 /* fixup cliprect (driDrawable may have changed?) later */
517 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
518 intelCopyBuffer(dPriv
, &rect
);
522 /* XXX this shouldn't be an error but we can't handle it for now */
523 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);