~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/i915tex/intel_buffers.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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_buffers.h"
 
32
#include "intel_depthstencil.h"
 
33
#include "intel_fbo.h"
 
34
#include "intel_tris.h"
 
35
#include "intel_regions.h"
 
36
#include "intel_batchbuffer.h"
 
37
#include "context.h"
 
38
#include "utils.h"
 
39
#include "framebuffer.h"
 
40
#include "swrast/swrast.h"
 
41
#include "vblank.h"
 
42
 
 
43
 
 
44
/**
 
45
 * XXX move this into a new dri/common/cliprects.c file.
 
46
 */
 
47
GLboolean
 
48
intel_intersect_cliprects(drm_clip_rect_t * dst,
 
49
                          const drm_clip_rect_t * a,
 
50
                          const drm_clip_rect_t * b)
 
51
{
 
52
   GLint bx = b->x1;
 
53
   GLint by = b->y1;
 
54
   GLint bw = b->x2 - bx;
 
55
   GLint bh = b->y2 - by;
 
56
 
 
57
   if (bx < a->x1)
 
58
      bw -= a->x1 - bx, bx = a->x1;
 
59
   if (by < a->y1)
 
60
      bh -= a->y1 - by, by = a->y1;
 
61
   if (bx + bw > a->x2)
 
62
      bw = a->x2 - bx;
 
63
   if (by + bh > a->y2)
 
64
      bh = a->y2 - by;
 
65
   if (bw <= 0)
 
66
      return GL_FALSE;
 
67
   if (bh <= 0)
 
68
      return GL_FALSE;
 
69
 
 
70
   dst->x1 = bx;
 
71
   dst->y1 = by;
 
72
   dst->x2 = bx + bw;
 
73
   dst->y2 = by + bh;
 
74
 
 
75
   return GL_TRUE;
 
76
}
 
77
 
 
78
/**
 
79
 * Return pointer to current color drawing region, or NULL.
 
80
 */
 
81
struct intel_region *
 
82
intel_drawbuf_region(struct intel_context *intel)
 
83
{
 
84
   struct intel_renderbuffer *irbColor =
 
85
      intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
 
86
   if (irbColor)
 
87
      return irbColor->region;
 
88
   else
 
89
      return NULL;
 
90
}
 
91
 
 
92
/**
 
93
 * Return pointer to current color reading region, or NULL.
 
94
 */
 
95
struct intel_region *
 
96
intel_readbuf_region(struct intel_context *intel)
 
97
{
 
98
   struct intel_renderbuffer *irb
 
99
      = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
 
100
   if (irb)
 
101
      return irb->region;
 
102
   else
 
103
      return NULL;
 
104
}
 
105
 
 
106
 
 
107
 
 
108
/**
 
109
 * Update the following fields for rendering to a user-created FBO:
 
110
 *   intel->numClipRects
 
111
 *   intel->pClipRects
 
112
 *   intel->drawX
 
113
 *   intel->drawY
 
114
 */
 
115
static void
 
116
intelSetRenderbufferClipRects(struct intel_context *intel)
 
117
{
 
118
   assert(intel->ctx.DrawBuffer->Width > 0);
 
119
   assert(intel->ctx.DrawBuffer->Height > 0);
 
120
   intel->fboRect.x1 = 0;
 
121
   intel->fboRect.y1 = 0;
 
122
   intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
 
123
   intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
 
124
   intel->numClipRects = 1;
 
125
   intel->pClipRects = &intel->fboRect;
 
126
   intel->drawX = 0;
 
127
   intel->drawY = 0;
 
128
}
 
129
 
 
130
 
 
131
/**
 
132
 * As above, but for rendering to front buffer of a window.
 
133
 * \sa intelSetRenderbufferClipRects
 
134
 */
 
135
static void
 
136
intelSetFrontClipRects(struct intel_context *intel)
 
137
{
 
138
   __DRIdrawablePrivate *dPriv = intel->driDrawable;
 
139
 
 
140
   if (!dPriv)
 
141
      return;
 
142
 
 
143
   intel->numClipRects = dPriv->numClipRects;
 
144
   intel->pClipRects = dPriv->pClipRects;
 
145
   intel->drawX = dPriv->x;
 
146
   intel->drawY = dPriv->y;
 
147
}
 
148
 
 
149
 
 
150
/**
 
151
 * As above, but for rendering to back buffer of a window.
 
152
 */
 
153
static void
 
154
intelSetBackClipRects(struct intel_context *intel)
 
155
{
 
156
   __DRIdrawablePrivate *dPriv = intel->driDrawable;
 
157
 
 
158
   if (!dPriv)
 
159
      return;
 
160
 
 
161
   if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
 
162
      /* use the front clip rects */
 
163
      intel->numClipRects = dPriv->numClipRects;
 
164
      intel->pClipRects = dPriv->pClipRects;
 
165
      intel->drawX = dPriv->x;
 
166
      intel->drawY = dPriv->y;
 
167
   }
 
168
   else {
 
169
      /* use the back clip rects */
 
170
      intel->numClipRects = dPriv->numBackClipRects;
 
171
      intel->pClipRects = dPriv->pBackClipRects;
 
172
      intel->drawX = dPriv->backX;
 
173
      intel->drawY = dPriv->backY;
 
174
   }
 
175
}
 
176
 
 
177
 
 
178
/**
 
179
 * This will be called whenever the currently bound window is moved/resized.
 
180
 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
 
181
 */
 
182
void
 
183
intelWindowMoved(struct intel_context *intel)
 
184
{
 
185
   GLcontext *ctx = &intel->ctx;
 
186
 
 
187
   if (!intel->ctx.DrawBuffer) {
 
188
      /* when would this happen? -BP */
 
189
      intelSetFrontClipRects(intel);
 
190
   }
 
191
   else if (intel->ctx.DrawBuffer->Name != 0) {
 
192
      /* drawing to user-created FBO - do nothing */
 
193
      /* Cliprects would be set from intelDrawBuffer() */
 
194
   }
 
195
   else {
 
196
      /* drawing to a window */
 
197
      switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
 
198
      case BUFFER_BIT_FRONT_LEFT:
 
199
         intelSetFrontClipRects(intel);
 
200
         break;
 
201
      case BUFFER_BIT_BACK_LEFT:
 
202
         intelSetBackClipRects(intel);
 
203
         break;
 
204
      default:
 
205
         /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
 
206
         intelSetFrontClipRects(intel);
 
207
      }
 
208
   }
 
209
 
 
210
   /* this update Mesa's notion of window size */
 
211
   if (ctx->WinSysDrawBuffer) {
 
212
      _mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer,
 
213
                               intel->driDrawable->w, intel->driDrawable->h);
 
214
   }
 
215
 
 
216
   if (intel->intelScreen->driScrnPriv->ddxMinor >= 7 && intel->driDrawable) {
 
217
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
 
218
      drmI830Sarea *sarea = intel->sarea;
 
219
      drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
 
220
                                   .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
 
221
      drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y,
 
222
                                     .x2 = sarea->pipeA_x + sarea->pipeA_w,
 
223
                                     .y2 = sarea->pipeA_y + sarea->pipeA_h };
 
224
      drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y,
 
225
                                     .x2 = sarea->pipeB_x + sarea->pipeB_w,
 
226
                                     .y2 = sarea->pipeB_y + sarea->pipeB_h };
 
227
      GLint areaA = driIntersectArea( drw_rect, pipeA_rect );
 
228
      GLint areaB = driIntersectArea( drw_rect, pipeB_rect );
 
229
      GLuint flags = intel->vblank_flags;
 
230
 
 
231
      if (areaB > areaA || (areaA == areaB && areaB > 0)) {
 
232
         flags = intel->vblank_flags | VBLANK_FLAG_SECONDARY;
 
233
      } else {
 
234
         flags = intel->vblank_flags & ~VBLANK_FLAG_SECONDARY;
 
235
      }
 
236
 
 
237
      if (flags != intel->vblank_flags) {
 
238
         intel->vblank_flags = flags;
 
239
         driGetCurrentVBlank(dPriv, intel->vblank_flags, &intel->vbl_seq);
 
240
      }
 
241
   } else {
 
242
      intel->vblank_flags &= ~VBLANK_FLAG_SECONDARY;
 
243
   }
 
244
 
 
245
   /* Update hardware scissor */
 
246
   ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
 
247
                       ctx->Scissor.Width, ctx->Scissor.Height);
 
248
}
 
249
 
 
250
 
 
251
 
 
252
/* A true meta version of this would be very simple and additionally
 
253
 * machine independent.  Maybe we'll get there one day.
 
254
 */
 
255
static void
 
256
intelClearWithTris(struct intel_context *intel, GLbitfield mask)
 
257
{
 
258
   GLcontext *ctx = &intel->ctx;
 
259
   drm_clip_rect_t clear;
 
260
 
 
261
   if (INTEL_DEBUG & DEBUG_BLIT)
 
262
      _mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
 
263
 
 
264
   LOCK_HARDWARE(intel);
 
265
 
 
266
   /* XXX FBO: was: intel->driDrawable->numClipRects */
 
267
   if (intel->numClipRects) {
 
268
      GLint cx, cy, cw, ch;
 
269
      GLuint buf;
 
270
 
 
271
      intel->vtbl.install_meta_state(intel);
 
272
 
 
273
      /* Get clear bounds after locking */
 
274
      cx = ctx->DrawBuffer->_Xmin;
 
275
      cy = ctx->DrawBuffer->_Ymin;
 
276
      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
 
277
      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
 
278
 
 
279
      /* note: regardless of 'all', cx, cy, cw, ch are now correct */
 
280
      clear.x1 = cx;
 
281
      clear.y1 = cy;
 
282
      clear.x2 = cx + cw;
 
283
      clear.y2 = cy + ch;
 
284
 
 
285
      /* Back and stencil cliprects are the same.  Try and do both
 
286
       * buffers at once:
 
287
       */
 
288
      if (mask &
 
289
          (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {
 
290
         struct intel_region *backRegion =
 
291
            intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT);
 
292
         struct intel_region *depthRegion =
 
293
            intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH);
 
294
         const GLuint clearColor = (backRegion && backRegion->cpp == 4)
 
295
            ? intel->ClearColor8888 : intel->ClearColor565;
 
296
 
 
297
         intel->vtbl.meta_draw_region(intel, backRegion, depthRegion);
 
298
 
 
299
         if (mask & BUFFER_BIT_BACK_LEFT)
 
300
            intel->vtbl.meta_color_mask(intel, GL_TRUE);
 
301
         else
 
302
            intel->vtbl.meta_color_mask(intel, GL_FALSE);
 
303
 
 
304
         if (mask & BUFFER_BIT_STENCIL)
 
305
            intel->vtbl.meta_stencil_replace(intel,
 
306
                                             intel->ctx.Stencil.WriteMask[0],
 
307
                                             intel->ctx.Stencil.Clear);
 
308
         else
 
309
            intel->vtbl.meta_no_stencil_write(intel);
 
310
 
 
311
         if (mask & BUFFER_BIT_DEPTH)
 
312
            intel->vtbl.meta_depth_replace(intel);
 
313
         else
 
314
            intel->vtbl.meta_no_depth_write(intel);
 
315
 
 
316
         /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
 
317
          * drawing origin may not be correctly emitted.
 
318
          */
 
319
         intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0);   /* texcoords */
 
320
 
 
321
         mask &=
 
322
            ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
 
323
      }
 
324
 
 
325
      /* clear the remaining (color) renderbuffers */
 
326
      for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
 
327
         const GLuint bufBit = 1 << buf;
 
328
         if (mask & bufBit) {
 
329
            struct intel_renderbuffer *irbColor =
 
330
               intel_renderbuffer(ctx->DrawBuffer->
 
331
                                  Attachment[buf].Renderbuffer);
 
332
            GLuint color = (irbColor->region->cpp == 4)
 
333
               ? intel->ClearColor8888 : intel->ClearColor565;
 
334
 
 
335
            ASSERT(irbColor);
 
336
 
 
337
            intel->vtbl.meta_no_depth_write(intel);
 
338
            intel->vtbl.meta_no_stencil_write(intel);
 
339
            intel->vtbl.meta_color_mask(intel, GL_TRUE);
 
340
            intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
 
341
 
 
342
            /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
 
343
             * drawing origin may not be correctly emitted.
 
344
             */
 
345
            intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, 0,      /* depth clear val */
 
346
                                 color, 0, 0, 0, 0);    /* texcoords */
 
347
 
 
348
            mask &= ~bufBit;
 
349
         }
 
350
      }
 
351
 
 
352
      intel->vtbl.leave_meta_state(intel);
 
353
      intel_batchbuffer_flush(intel->batch);
 
354
   }
 
355
   UNLOCK_HARDWARE(intel);
 
356
}
 
357
 
 
358
 
 
359
 
 
360
 
 
361
/**
 
362
 * Copy the window contents named by dPriv to the rotated (or reflected)
 
363
 * color buffer.
 
364
 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
 
365
 */
 
366
void
 
367
intelRotateWindow(struct intel_context *intel,
 
368
                  __DRIdrawablePrivate * dPriv, GLuint srcBuf)
 
369
{
 
370
   intelScreenPrivate *screen = intel->intelScreen;
 
371
   drm_clip_rect_t fullRect;
 
372
   struct intel_region *src;
 
373
   const drm_clip_rect_t *clipRects;
 
374
   int numClipRects;
 
375
   int i;
 
376
   GLenum format, type;
 
377
 
 
378
   int xOrig, yOrig;
 
379
   int origNumClipRects;
 
380
   drm_clip_rect_t *origRects;
 
381
 
 
382
   /*
 
383
    * set up hardware state
 
384
    */
 
385
   intelFlush(&intel->ctx);
 
386
 
 
387
   LOCK_HARDWARE(intel);
 
388
 
 
389
   if (!intel->numClipRects) {
 
390
      UNLOCK_HARDWARE(intel);
 
391
      return;
 
392
   }
 
393
 
 
394
   intel->vtbl.install_meta_state(intel);
 
395
 
 
396
   intel->vtbl.meta_no_depth_write(intel);
 
397
   intel->vtbl.meta_no_stencil_write(intel);
 
398
   intel->vtbl.meta_color_mask(intel, GL_FALSE);
 
399
 
 
400
 
 
401
   /* save current drawing origin and cliprects (restored at end) */
 
402
   xOrig = intel->drawX;
 
403
   yOrig = intel->drawY;
 
404
   origNumClipRects = intel->numClipRects;
 
405
   origRects = intel->pClipRects;
 
406
 
 
407
   /*
 
408
    * set drawing origin, cliprects for full-screen access to rotated screen
 
409
    */
 
410
   fullRect.x1 = 0;
 
411
   fullRect.y1 = 0;
 
412
   fullRect.x2 = screen->rotatedWidth;
 
413
   fullRect.y2 = screen->rotatedHeight;
 
414
   intel->drawX = 0;
 
415
   intel->drawY = 0;
 
416
   intel->numClipRects = 1;
 
417
   intel->pClipRects = &fullRect;
 
418
 
 
419
   intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL);    /* ? */
 
420
 
 
421
   if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
 
422
      src = intel->intelScreen->front_region;
 
423
      clipRects = dPriv->pClipRects;
 
424
      numClipRects = dPriv->numClipRects;
 
425
   }
 
426
   else {
 
427
      src = intel->intelScreen->back_region;
 
428
      clipRects = dPriv->pBackClipRects;
 
429
      numClipRects = dPriv->numBackClipRects;
 
430
   }
 
431
 
 
432
   if (src->cpp == 4) {
 
433
      format = GL_BGRA;
 
434
      type = GL_UNSIGNED_BYTE;
 
435
   }
 
436
   else {
 
437
      format = GL_BGR;
 
438
      type = GL_UNSIGNED_SHORT_5_6_5_REV;
 
439
   }
 
440
 
 
441
   /* set the whole screen up as a texture to avoid alignment issues */
 
442
   intel->vtbl.meta_tex_rect_source(intel,
 
443
                                    src->buffer,
 
444
                                    screen->width,
 
445
                                    screen->height, src->pitch, format, type);
 
446
 
 
447
   intel->vtbl.meta_texture_blend_replace(intel);
 
448
 
 
449
   /*
 
450
    * loop over the source window's cliprects
 
451
    */
 
452
   for (i = 0; i < numClipRects; i++) {
 
453
      int srcX0 = clipRects[i].x1;
 
454
      int srcY0 = clipRects[i].y1;
 
455
      int srcX1 = clipRects[i].x2;
 
456
      int srcY1 = clipRects[i].y2;
 
457
      GLfloat verts[4][2], tex[4][2];
 
458
      int j;
 
459
 
 
460
      /* build vertices for four corners of clip rect */
 
461
      verts[0][0] = srcX0;
 
462
      verts[0][1] = srcY0;
 
463
      verts[1][0] = srcX1;
 
464
      verts[1][1] = srcY0;
 
465
      verts[2][0] = srcX1;
 
466
      verts[2][1] = srcY1;
 
467
      verts[3][0] = srcX0;
 
468
      verts[3][1] = srcY1;
 
469
 
 
470
      /* .. and texcoords */
 
471
      tex[0][0] = srcX0;
 
472
      tex[0][1] = srcY0;
 
473
      tex[1][0] = srcX1;
 
474
      tex[1][1] = srcY0;
 
475
      tex[2][0] = srcX1;
 
476
      tex[2][1] = srcY1;
 
477
      tex[3][0] = srcX0;
 
478
      tex[3][1] = srcY1;
 
479
 
 
480
      /* transform coords to rotated screen coords */
 
481
 
 
482
      for (j = 0; j < 4; j++) {
 
483
         matrix23TransformCoordf(&screen->rotMatrix,
 
484
                                 &verts[j][0], &verts[j][1]);
 
485
      }
 
486
 
 
487
      /* draw polygon to map source image to dest region */
 
488
      intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
 
489
 
 
490
   }                            /* cliprect loop */
 
491
 
 
492
   intel->vtbl.leave_meta_state(intel);
 
493
   intel_batchbuffer_flush(intel->batch);
 
494
 
 
495
   /* restore original drawing origin and cliprects */
 
496
   intel->drawX = xOrig;
 
497
   intel->drawY = yOrig;
 
498
   intel->numClipRects = origNumClipRects;
 
499
   intel->pClipRects = origRects;
 
500
 
 
501
   UNLOCK_HARDWARE(intel);
 
502
}
 
503
 
 
504
 
 
505
/**
 
506
 * Called by ctx->Driver.Clear.
 
507
 */
 
508
static void
 
509
intelClear(GLcontext *ctx, GLbitfield mask)
 
510
{
 
511
   struct intel_context *intel = intel_context(ctx);
 
512
   const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
 
513
   GLbitfield tri_mask = 0;
 
514
   GLbitfield blit_mask = 0;
 
515
   GLbitfield swrast_mask = 0;
 
516
   GLuint i;
 
517
 
 
518
   if (0)
 
519
      fprintf(stderr, "%s\n", __FUNCTION__);
 
520
 
 
521
   /* HW color buffers (front, back, aux, generic FBO, etc) */
 
522
   if (colorMask == ~0) {
 
523
      /* clear all R,G,B,A */
 
524
      /* XXX FBO: need to check if colorbuffers are software RBOs! */
 
525
      blit_mask |= (mask & BUFFER_BITS_COLOR);
 
526
   }
 
527
   else {
 
528
      /* glColorMask in effect */
 
529
      tri_mask |= (mask & BUFFER_BITS_COLOR);
 
530
   }
 
531
 
 
532
   /* HW stencil */
 
533
   if (mask & BUFFER_BIT_STENCIL) {
 
534
      const struct intel_region *stencilRegion
 
535
         = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL);
 
536
      if (stencilRegion) {
 
537
         /* have hw stencil */
 
538
         if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
 
539
            /* not clearing all stencil bits, so use triangle clearing */
 
540
            tri_mask |= BUFFER_BIT_STENCIL;
 
541
         }
 
542
         else {
 
543
            /* clearing all stencil bits, use blitting */
 
544
            blit_mask |= BUFFER_BIT_STENCIL;
 
545
         }
 
546
      }
 
547
   }
 
548
 
 
549
   /* HW depth */
 
550
   if (mask & BUFFER_BIT_DEPTH) {
 
551
      /* clear depth with whatever method is used for stencil (see above) */
 
552
      if (tri_mask & BUFFER_BIT_STENCIL)
 
553
         tri_mask |= BUFFER_BIT_DEPTH;
 
554
      else
 
555
         blit_mask |= BUFFER_BIT_DEPTH;
 
556
   }
 
557
 
 
558
   /* SW fallback clearing */
 
559
   swrast_mask = mask & ~tri_mask & ~blit_mask;
 
560
 
 
561
   for (i = 0; i < BUFFER_COUNT; i++) {
 
562
      GLuint bufBit = 1 << i;
 
563
      if ((blit_mask | tri_mask) & bufBit) {
 
564
         if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
 
565
            blit_mask &= ~bufBit;
 
566
            tri_mask &= ~bufBit;
 
567
            swrast_mask |= bufBit;
 
568
         }
 
569
      }
 
570
   }
 
571
 
 
572
 
 
573
   intelFlush(ctx);             /* XXX intelClearWithBlit also does this */
 
574
 
 
575
   if (blit_mask)
 
576
      intelClearWithBlit(ctx, blit_mask);
 
577
 
 
578
   if (tri_mask)
 
579
      intelClearWithTris(intel, tri_mask);
 
580
 
 
581
   if (swrast_mask)
 
582
      _swrast_Clear(ctx, swrast_mask);
 
583
}
 
584
 
 
585
 
 
586
 
 
587
/* Flip the front & back buffers
 
588
 */
 
589
static void
 
590
intelPageFlip(const __DRIdrawablePrivate * dPriv)
 
591
{
 
592
#if 0
 
593
   struct intel_context *intel;
 
594
   int tmp, ret;
 
595
 
 
596
   if (INTEL_DEBUG & DEBUG_IOCTL)
 
597
      fprintf(stderr, "%s\n", __FUNCTION__);
 
598
 
 
599
   assert(dPriv);
 
600
   assert(dPriv->driContextPriv);
 
601
   assert(dPriv->driContextPriv->driverPrivate);
 
602
 
 
603
   intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
 
604
 
 
605
   intelFlush(&intel->ctx);
 
606
   LOCK_HARDWARE(intel);
 
607
 
 
608
   if (dPriv->pClipRects) {
 
609
      *(drm_clip_rect_t *) intel->sarea->boxes = dPriv->pClipRects[0];
 
610
      intel->sarea->nbox = 1;
 
611
   }
 
612
 
 
613
   ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
 
614
   if (ret) {
 
615
      fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
 
616
      UNLOCK_HARDWARE(intel);
 
617
      exit(1);
 
618
   }
 
619
 
 
620
   tmp = intel->sarea->last_enqueue;
 
621
   intelRefillBatchLocked(intel);
 
622
   UNLOCK_HARDWARE(intel);
 
623
 
 
624
 
 
625
   intelSetDrawBuffer(&intel->ctx, intel->ctx.Color.DriverDrawBuffer);
 
626
#endif
 
627
}
 
628
 
 
629
#if 0
 
630
void
 
631
intelSwapBuffers(__DRIdrawablePrivate * dPriv)
 
632
{
 
633
   if (dPriv->driverPrivate) {
 
634
      const struct gl_framebuffer *fb
 
635
         = (struct gl_framebuffer *) dPriv->driverPrivate;
 
636
      if (fb->Visual.doubleBufferMode) {
 
637
         GET_CURRENT_CONTEXT(ctx);
 
638
         if (ctx && ctx->DrawBuffer == fb) {
 
639
            _mesa_notifySwapBuffers(ctx);       /* flush pending rendering */
 
640
         }
 
641
         if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */
 
642
            intelPageFlip(dPriv);
 
643
         }
 
644
         else {
 
645
            intelCopyBuffer(dPriv);
 
646
         }
 
647
      }
 
648
   }
 
649
   else {
 
650
      _mesa_problem(NULL,
 
651
                    "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
 
652
   }
 
653
}
 
654
#else
 
655
/* Trunk version:
 
656
 */
 
657
void
 
658
intelSwapBuffers(__DRIdrawablePrivate * dPriv)
 
659
{
 
660
   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
 
661
      GET_CURRENT_CONTEXT(ctx);
 
662
      struct intel_context *intel;
 
663
 
 
664
      if (ctx == NULL)
 
665
         return;
 
666
 
 
667
      intel = intel_context(ctx);
 
668
 
 
669
      if (ctx->Visual.doubleBufferMode) {
 
670
         intelScreenPrivate *screen = intel->intelScreen;
 
671
         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
 
672
         if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */
 
673
            intelPageFlip(dPriv);
 
674
         }
 
675
         else {
 
676
            intelCopyBuffer(dPriv, NULL);
 
677
         }
 
678
         if (screen->current_rotation != 0) {
 
679
            intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
 
680
         }
 
681
      }
 
682
   }
 
683
   else {
 
684
      /* XXX this shouldn't be an error but we can't handle it for now */
 
685
      fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
 
686
   }
 
687
}
 
688
#endif
 
689
 
 
690
void
 
691
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
 
692
{
 
693
   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
 
694
      struct intel_context *intel =
 
695
         (struct intel_context *) dPriv->driContextPriv->driverPrivate;
 
696
      GLcontext *ctx = &intel->ctx;
 
697
 
 
698
      if (ctx->Visual.doubleBufferMode) {
 
699
         drm_clip_rect_t rect;
 
700
         rect.x1 = x + dPriv->x;
 
701
         rect.y1 = (dPriv->h - y - h) + dPriv->y;
 
702
         rect.x2 = rect.x1 + w;
 
703
         rect.y2 = rect.y1 + h;
 
704
         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
 
705
         intelCopyBuffer(dPriv, &rect);
 
706
      }
 
707
   }
 
708
   else {
 
709
      /* XXX this shouldn't be an error but we can't handle it for now */
 
710
      fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
 
711
   }
 
712
}
 
713
 
 
714
 
 
715
/**
 
716
 * Update the hardware state for drawing into a window or framebuffer object.
 
717
 *
 
718
 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
 
719
 * places within the driver.
 
720
 *
 
721
 * Basically, this needs to be called any time the current framebuffer
 
722
 * changes, the renderbuffers change, or we need to draw into different
 
723
 * color buffers.
 
724
 */
 
725
void
 
726
intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
 
727
{
 
728
   struct intel_context *intel = intel_context(ctx);
 
729
   struct intel_region *colorRegion, *depthRegion = NULL;
 
730
   struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
 
731
   int front = 0;               /* drawing to front color buffer? */
 
732
 
 
733
   if (!fb) {
 
734
      /* this can happen during the initial context initialization */
 
735
      return;
 
736
   }
 
737
 
 
738
   /* Do this here, note core Mesa, since this function is called from
 
739
    * many places within the driver.
 
740
    */
 
741
   if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
 
742
      /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
 
743
      _mesa_update_framebuffer(ctx);
 
744
      /* this updates the DrawBuffer's Width/Height if it's a FBO */
 
745
      _mesa_update_draw_buffer_bounds(ctx);
 
746
   }
 
747
 
 
748
   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
 
749
      /* this may occur when we're called by glBindFrameBuffer() during
 
750
       * the process of someone setting up renderbuffers, etc.
 
751
       */
 
752
      /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
 
753
      return;
 
754
   }
 
755
 
 
756
   if (fb->Name)
 
757
      intel_validate_paired_depth_stencil(ctx, fb);
 
758
 
 
759
   /*
 
760
    * How many color buffers are we drawing into?
 
761
    */
 
762
   if (fb->_NumColorDrawBuffers[0] != 1
 
763
#if 0
 
764
       /* XXX FBO temporary - always use software rendering */
 
765
       || 1
 
766
#endif
 
767
      ) {
 
768
      /* writing to 0 or 2 or 4 color buffers */
 
769
      /*_mesa_debug(ctx, "Software rendering\n");*/
 
770
      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
 
771
      front = 1;                /* might not have back color buffer */
 
772
   }
 
773
   else {
 
774
      /* draw to exactly one color buffer */
 
775
      /*_mesa_debug(ctx, "Hardware rendering\n");*/
 
776
      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
 
777
      if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
 
778
         front = 1;
 
779
      }
 
780
   }
 
781
 
 
782
   /*
 
783
    * Get the intel_renderbuffer for the colorbuffer we're drawing into.
 
784
    * And set up cliprects.
 
785
    */
 
786
   if (fb->Name == 0) {
 
787
      /* drawing to window system buffer */
 
788
      if (intel->sarea->pf_current_page == 1) {
 
789
         /* page flipped back/front */
 
790
         front ^= 1;
 
791
      }
 
792
      if (front) {
 
793
         intelSetFrontClipRects(intel);
 
794
         colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
 
795
      }
 
796
      else {
 
797
         intelSetBackClipRects(intel);
 
798
         colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
 
799
      }
 
800
   }
 
801
   else {
 
802
      /* drawing to user-created FBO */
 
803
      struct intel_renderbuffer *irb;
 
804
      intelSetRenderbufferClipRects(intel);
 
805
      irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
 
806
      colorRegion = (irb && irb->region) ? irb->region : NULL;
 
807
   }
 
808
 
 
809
   /* Update culling direction which changes depending on the
 
810
    * orientation of the buffer:
 
811
    */
 
812
   if (ctx->Driver.FrontFace)
 
813
      ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
 
814
   else
 
815
      ctx->NewState |= _NEW_POLYGON;
 
816
 
 
817
   if (!colorRegion) {
 
818
      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
 
819
   }
 
820
   else {
 
821
      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
 
822
   }
 
823
 
 
824
   /***
 
825
    *** Get depth buffer region and check if we need a software fallback.
 
826
    *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
 
827
    ***/
 
828
   if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
 
829
      irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
 
830
      if (irbDepth && irbDepth->region) {
 
831
         FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
 
832
         depthRegion = irbDepth->region;
 
833
      }
 
834
      else {
 
835
         FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
 
836
         depthRegion = NULL;
 
837
      }
 
838
   }
 
839
   else {
 
840
      /* not using depth buffer */
 
841
      FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
 
842
      depthRegion = NULL;
 
843
   }
 
844
 
 
845
   /***
 
846
    *** Stencil buffer
 
847
    *** This can only be hardware accelerated if we're using a
 
848
    *** combined DEPTH_STENCIL buffer (for now anyway).
 
849
    ***/
 
850
   if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
 
851
      irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
 
852
      if (irbStencil && irbStencil->region) {
 
853
         ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
 
854
         FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
 
855
         /* need to re-compute stencil hw state */
 
856
         ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
 
857
         if (!depthRegion)
 
858
            depthRegion = irbStencil->region;
 
859
      }
 
860
      else {
 
861
         FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
 
862
      }
 
863
   }
 
864
   else {
 
865
      /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
 
866
      FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
 
867
      /* need to re-compute stencil hw state */
 
868
      ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
 
869
   }
 
870
 
 
871
 
 
872
   /**
 
873
    ** Release old regions, reference new regions
 
874
    **/
 
875
#if 0                           /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
 
876
   if (intel->draw_region != colorRegion) {
 
877
      intel_region_release(&intel->draw_region);
 
878
      intel_region_reference(&intel->draw_region, colorRegion);
 
879
   }
 
880
   if (intel->intelScreen->depth_region != depthRegion) {
 
881
      intel_region_release(&intel->intelScreen->depth_region);
 
882
      intel_region_reference(&intel->intelScreen->depth_region, depthRegion);
 
883
   }
 
884
#endif
 
885
 
 
886
   intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
 
887
 
 
888
   /* update viewport since it depends on window size */
 
889
   ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
 
890
                        ctx->Viewport.Width, ctx->Viewport.Height);
 
891
 
 
892
   /* Update hardware scissor */
 
893
   ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
 
894
                       ctx->Scissor.Width, ctx->Scissor.Height);
 
895
}
 
896
 
 
897
 
 
898
static void
 
899
intelDrawBuffer(GLcontext * ctx, GLenum mode)
 
900
{
 
901
   intel_draw_buffer(ctx, ctx->DrawBuffer);
 
902
}
 
903
 
 
904
 
 
905
static void
 
906
intelReadBuffer(GLcontext * ctx, GLenum mode)
 
907
{
 
908
   if (ctx->ReadBuffer == ctx->DrawBuffer) {
 
909
      /* This will update FBO completeness status.
 
910
       * A framebuffer will be incomplete if the GL_READ_BUFFER setting
 
911
       * refers to a missing renderbuffer.  Calling glReadBuffer can set
 
912
       * that straight and can make the drawing buffer complete.
 
913
       */
 
914
      intel_draw_buffer(ctx, ctx->DrawBuffer);
 
915
   }
 
916
   /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
 
917
    * reference ctx->ReadBuffer and do appropriate state checks.
 
918
    */
 
919
}
 
920
 
 
921
 
 
922
void
 
923
intelInitBufferFuncs(struct dd_function_table *functions)
 
924
{
 
925
   functions->Clear = intelClear;
 
926
   functions->DrawBuffer = intelDrawBuffer;
 
927
   functions->ReadBuffer = intelReadBuffer;
 
928
}