Remove Driver.ResizeBuffers = _mesa_resize_framebuffer lines.
[mesa.git] / src / mesa / drivers / dri / i965 / intel_buffers.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 #include "intel_screen.h"
29 #include "intel_context.h"
30 #include "intel_blit.h"
31 #include "intel_regions.h"
32 #include "intel_batchbuffer.h"
33 #include "context.h"
34 #include "framebuffer.h"
35 #include "macros.h"
36 #include "swrast/swrast.h"
37
38 GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
39 const drm_clip_rect_t *a,
40 const drm_clip_rect_t *b )
41 {
42 dst->x1 = MAX2(a->x1, b->x1);
43 dst->x2 = MIN2(a->x2, b->x2);
44 dst->y1 = MAX2(a->y1, b->y1);
45 dst->y2 = MIN2(a->y2, b->y2);
46
47 return (dst->x1 <= dst->x2 &&
48 dst->y1 <= dst->y2);
49 }
50
51 struct intel_region *intel_drawbuf_region( struct intel_context *intel )
52 {
53 switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
54 case BUFFER_BIT_FRONT_LEFT:
55 return intel->front_region;
56 case BUFFER_BIT_BACK_LEFT:
57 return intel->back_region;
58 default:
59 /* Not necessary to fallback - could handle either NONE or
60 * FRONT_AND_BACK cases below.
61 */
62 return NULL;
63 }
64 }
65
66 struct intel_region *intel_readbuf_region( struct intel_context *intel )
67 {
68 GLcontext *ctx = &intel->ctx;
69
70 /* This will have to change to support EXT_fbo's, but is correct
71 * for now:
72 */
73 switch (ctx->ReadBuffer->_ColorReadBufferIndex) {
74 case BUFFER_FRONT_LEFT:
75 return intel->front_region;
76 case BUFFER_BACK_LEFT:
77 return intel->back_region;
78 default:
79 assert(0);
80 return NULL;
81 }
82 }
83
84
85
86 static void intelBufferSize(GLframebuffer *buffer,
87 GLuint *width,
88 GLuint *height)
89 {
90 GET_CURRENT_CONTEXT(ctx);
91 struct intel_context *intel = intel_context(ctx);
92 /* Need to lock to make sure the driDrawable is uptodate. This
93 * information is used to resize Mesa's software buffers, so it has
94 * to be correct.
95 */
96 LOCK_HARDWARE(intel);
97 if (intel->driDrawable) {
98 *width = intel->driDrawable->w;
99 *height = intel->driDrawable->h;
100 }
101 else {
102 *width = 0;
103 *height = 0;
104 }
105 UNLOCK_HARDWARE(intel);
106 }
107
108
109 static void intelSetFrontClipRects( struct intel_context *intel )
110 {
111 __DRIdrawablePrivate *dPriv = intel->driDrawable;
112
113 if (!dPriv) return;
114
115 intel->numClipRects = dPriv->numClipRects;
116 intel->pClipRects = dPriv->pClipRects;
117 intel->drawX = dPriv->x;
118 intel->drawY = dPriv->y;
119 }
120
121
122 static void intelSetBackClipRects( struct intel_context *intel )
123 {
124 __DRIdrawablePrivate *dPriv = intel->driDrawable;
125
126 if (!dPriv) return;
127
128 if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
129 intel->numClipRects = dPriv->numClipRects;
130 intel->pClipRects = dPriv->pClipRects;
131 intel->drawX = dPriv->x;
132 intel->drawY = dPriv->y;
133 } else {
134 intel->numClipRects = dPriv->numBackClipRects;
135 intel->pClipRects = dPriv->pBackClipRects;
136 intel->drawX = dPriv->backX;
137 intel->drawY = dPriv->backY;
138
139 if (dPriv->numBackClipRects == 1 &&
140 dPriv->x == dPriv->backX &&
141 dPriv->y == dPriv->backY) {
142
143 /* Repeat the calculation of the back cliprect dimensions here
144 * as early versions of dri.a in the Xserver are incorrect. Try
145 * very hard not to restrict future versions of dri.a which
146 * might eg. allocate truly private back buffers.
147 */
148 int x1, y1;
149 int x2, y2;
150
151 x1 = dPriv->x;
152 y1 = dPriv->y;
153 x2 = dPriv->x + dPriv->w;
154 y2 = dPriv->y + dPriv->h;
155
156 if (x1 < 0) x1 = 0;
157 if (y1 < 0) y1 = 0;
158 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
159 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
160
161 if (x1 == dPriv->pBackClipRects[0].x1 &&
162 y1 == dPriv->pBackClipRects[0].y1) {
163
164 dPriv->pBackClipRects[0].x2 = x2;
165 dPriv->pBackClipRects[0].y2 = y2;
166 }
167 }
168 }
169 }
170
171
172 void intelWindowMoved( struct intel_context *intel )
173 {
174 __DRIdrawablePrivate *dPriv = intel->driDrawable;
175
176 if (!intel->ctx.DrawBuffer) {
177 intelSetFrontClipRects( intel );
178 }
179 else {
180 switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
181 case BUFFER_BIT_FRONT_LEFT:
182 intelSetFrontClipRects( intel );
183 break;
184 case BUFFER_BIT_BACK_LEFT:
185 intelSetBackClipRects( intel );
186 break;
187 default:
188 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
189 intelSetFrontClipRects( intel );
190 }
191 }
192
193 _mesa_resize_framebuffer(&intel->ctx,
194 (GLframebuffer*)dPriv->driverPrivate,
195 dPriv->w, dPriv->h);
196
197 /* Set state we know depends on drawable parameters:
198 */
199 {
200 GLcontext *ctx = &intel->ctx;
201
202 if (ctx->Driver.Scissor)
203 ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
204 ctx->Scissor.Width, ctx->Scissor.Height );
205
206 if (ctx->Driver.DepthRange)
207 ctx->Driver.DepthRange( ctx,
208 ctx->Viewport.Near,
209 ctx->Viewport.Far );
210
211 intel->NewGLState |= _NEW_SCISSOR;
212 }
213 }
214
215
216
217 /* A true meta version of this would be very simple and additionally
218 * machine independent. Maybe we'll get there one day.
219 */
220 static void intelClearWithTris(struct intel_context *intel,
221 GLbitfield mask,
222 GLboolean all,
223 GLint cx, GLint cy,
224 GLint cw, GLint ch)
225 {
226 drm_clip_rect_t clear;
227
228 if (INTEL_DEBUG & DEBUG_DRI)
229 _mesa_printf("%s %x\n", __FUNCTION__, mask);
230
231 {
232
233 intel->vtbl.install_meta_state(intel);
234
235 /* Refresh the cx/y/w/h values as they may have been invalidated
236 * by a new window position or size picked up when we did
237 * LOCK_HARDWARE above. The values passed by mesa are not
238 * reliable.
239 */
240 {
241 GLcontext *ctx = &intel->ctx;
242 cx = ctx->DrawBuffer->_Xmin;
243 cy = ctx->DrawBuffer->_Ymin;
244 ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
245 cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
246 }
247
248 clear.x1 = cx;
249 clear.y1 = cy;
250 clear.x2 = cx + cw;
251 clear.y2 = cy + ch;
252
253 /* Back and stencil cliprects are the same. Try and do both
254 * buffers at once:
255 */
256 if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH)) {
257 intel->vtbl.meta_draw_region(intel,
258 intel->back_region,
259 intel->depth_region );
260
261 if (mask & BUFFER_BIT_BACK_LEFT)
262 intel->vtbl.meta_color_mask(intel, GL_TRUE );
263 else
264 intel->vtbl.meta_color_mask(intel, GL_FALSE );
265
266 if (mask & BUFFER_BIT_STENCIL)
267 intel->vtbl.meta_stencil_replace( intel,
268 intel->ctx.Stencil.WriteMask[0],
269 intel->ctx.Stencil.Clear);
270 else
271 intel->vtbl.meta_no_stencil_write(intel);
272
273 if (mask & BUFFER_BIT_DEPTH)
274 intel->vtbl.meta_depth_replace( intel );
275 else
276 intel->vtbl.meta_no_depth_write(intel);
277
278 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
279 * drawing origin may not be correctly emitted.
280 */
281 intel->vtbl.meta_draw_quad(intel,
282 clear.x1, clear.x2,
283 clear.y1, clear.y2,
284 intel->ctx.Depth.Clear,
285 intel->clear_chan[0],
286 intel->clear_chan[1],
287 intel->clear_chan[2],
288 intel->clear_chan[3],
289 0, 0, 0, 0);
290 }
291
292 /* Front may have different cliprects:
293 */
294 if (mask & BUFFER_BIT_FRONT_LEFT) {
295 intel->vtbl.meta_no_depth_write(intel);
296 intel->vtbl.meta_no_stencil_write(intel);
297 intel->vtbl.meta_color_mask(intel, GL_TRUE );
298 intel->vtbl.meta_draw_region(intel,
299 intel->front_region,
300 intel->depth_region);
301
302 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
303 * drawing origin may not be correctly emitted.
304 */
305 intel->vtbl.meta_draw_quad(intel,
306 clear.x1, clear.x2,
307 clear.y1, clear.y2,
308 0,
309 intel->clear_chan[0],
310 intel->clear_chan[1],
311 intel->clear_chan[2],
312 intel->clear_chan[3],
313 0, 0, 0, 0);
314 }
315
316 intel->vtbl.leave_meta_state( intel );
317 }
318 }
319
320
321
322
323
324 static void intelClear(GLcontext *ctx,
325 GLbitfield mask,
326 GLboolean all,
327 GLint cx, GLint cy,
328 GLint cw, GLint ch)
329 {
330 struct intel_context *intel = intel_context( ctx );
331 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
332 GLbitfield tri_mask = 0;
333 GLbitfield blit_mask = 0;
334 GLbitfield swrast_mask = 0;
335
336 if (INTEL_DEBUG & DEBUG_DRI)
337 fprintf(stderr, "%s %x all %d dims %d,%d %dx%d\n", __FUNCTION__,
338 mask, all, cx, cy, cw, ch);
339
340
341 if (mask & BUFFER_BIT_FRONT_LEFT) {
342 if (colorMask == ~0) {
343 blit_mask |= BUFFER_BIT_FRONT_LEFT;
344 }
345 else {
346 tri_mask |= BUFFER_BIT_FRONT_LEFT;
347 }
348 }
349
350 if (mask & BUFFER_BIT_BACK_LEFT) {
351 if (colorMask == ~0) {
352 blit_mask |= BUFFER_BIT_BACK_LEFT;
353 }
354 else {
355 tri_mask |= BUFFER_BIT_BACK_LEFT;
356 }
357 }
358
359
360 if (mask & BUFFER_BIT_STENCIL) {
361 if (!intel->hw_stencil) {
362 swrast_mask |= BUFFER_BIT_STENCIL;
363 }
364 else if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff ||
365 intel->depth_region->tiled) {
366 tri_mask |= BUFFER_BIT_STENCIL;
367 }
368 else {
369 blit_mask |= BUFFER_BIT_STENCIL;
370 }
371 }
372
373 /* Do depth with stencil if possible to avoid 2nd pass over the
374 * same buffer.
375 */
376 if (mask & BUFFER_BIT_DEPTH) {
377 if ((tri_mask & BUFFER_BIT_STENCIL) ||
378 intel->depth_region->tiled)
379 tri_mask |= BUFFER_BIT_DEPTH;
380 else
381 blit_mask |= BUFFER_BIT_DEPTH;
382 }
383
384 swrast_mask |= (mask & BUFFER_BIT_ACCUM);
385
386 intelFlush( ctx );
387
388 if (blit_mask)
389 intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
390
391 if (tri_mask)
392 intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch);
393
394 if (swrast_mask)
395 _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
396 }
397
398
399
400
401
402
403
404 /* Flip the front & back buffers
405 */
406 static void intelPageFlip( const __DRIdrawablePrivate *dPriv )
407 {
408 #if 0
409 struct intel_context *intel;
410 int tmp, ret;
411
412 if (INTEL_DEBUG & DEBUG_IOCTL)
413 fprintf(stderr, "%s\n", __FUNCTION__);
414
415 assert(dPriv);
416 assert(dPriv->driContextPriv);
417 assert(dPriv->driContextPriv->driverPrivate);
418
419 intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
420
421 intelFlush( &intel->ctx );
422 LOCK_HARDWARE( intel );
423
424 if (dPriv->pClipRects) {
425 *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
426 intel->sarea->nbox = 1;
427 }
428
429 ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
430 if (ret) {
431 fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
432 UNLOCK_HARDWARE( intel );
433 exit(1);
434 }
435
436 tmp = intel->sarea->last_enqueue;
437 intelRefillBatchLocked( intel );
438 UNLOCK_HARDWARE( intel );
439
440
441 intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
442 #endif
443 }
444
445
446 void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
447 {
448 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
449 struct intel_context *intel;
450 GLcontext *ctx;
451 intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
452 ctx = &intel->ctx;
453 if (ctx->Visual.doubleBufferMode) {
454 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
455 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
456 intelPageFlip( dPriv );
457 } else {
458 intelCopyBuffer( dPriv, NULL );
459 }
460 if (intel->aub_file) {
461 intelFlush(ctx);
462 intel->vtbl.aub_dump_bmp( intel, 1 );
463
464 intel->aub_wrap = 1;
465 }
466 }
467 } else {
468 /* XXX this shouldn't be an error but we can't handle it for now */
469 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
470 }
471 }
472
473 void intelCopySubBuffer( __DRIdrawablePrivate *dPriv,
474 int x, int y, int w, int h )
475 {
476 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
477 struct intel_context *intel = dPriv->driContextPriv->driverPrivate;
478 GLcontext *ctx = &intel->ctx;
479
480 if (ctx->Visual.doubleBufferMode) {
481 drm_clip_rect_t rect;
482 rect.x1 = x + dPriv->x;
483 rect.y1 = (dPriv->h - y - h) + dPriv->y;
484 rect.x2 = rect.x1 + w;
485 rect.y2 = rect.y1 + h;
486 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
487 intelCopyBuffer( dPriv, &rect );
488 }
489 } else {
490 /* XXX this shouldn't be an error but we can't handle it for now */
491 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
492 }
493 }
494
495
496 static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
497 {
498 struct intel_context *intel = intel_context(ctx);
499 int front = 0;
500
501 if (!ctx->DrawBuffer)
502 return;
503
504 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
505 case BUFFER_BIT_FRONT_LEFT:
506 front = 1;
507 FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
508 break;
509 case BUFFER_BIT_BACK_LEFT:
510 front = 0;
511 FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
512 break;
513 default:
514 FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
515 return;
516 }
517
518 if ( intel->sarea->pf_current_page == 1 )
519 front ^= 1;
520
521 intelSetFrontClipRects( intel );
522
523
524 if (front) {
525 if (intel->draw_region != intel->front_region) {
526 intel_region_release(intel, &intel->draw_region);
527 intel_region_reference(&intel->draw_region, intel->front_region);
528 }
529 } else {
530 if (intel->draw_region != intel->back_region) {
531 intel_region_release(intel, &intel->draw_region);
532 intel_region_reference(&intel->draw_region, intel->back_region);
533 }
534 }
535
536 intel->vtbl.set_draw_region( intel,
537 intel->draw_region,
538 intel->depth_region);
539 }
540
541 static void intelReadBuffer( GLcontext *ctx, GLenum mode )
542 {
543 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
544 }
545
546
547
548 void intelInitBufferFuncs( struct dd_function_table *functions )
549 {
550 functions->Clear = intelClear;
551 functions->GetBufferSize = intelBufferSize;
552 functions->DrawBuffer = intelDrawBuffer;
553 functions->ReadBuffer = intelReadBuffer;
554 }