~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/mesa/state_tracker/st_framebuffer.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

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
 
 
29
 
#include "main/imports.h"
30
 
#include "main/buffers.h"
31
 
#include "main/context.h"
32
 
#include "main/framebuffer.h"
33
 
#include "main/renderbuffer.h"
34
 
#include "st_context.h"
35
 
#include "st_cb_fbo.h"
36
 
#include "st_public.h"
37
 
#include "pipe/p_defines.h"
38
 
#include "util/u_inlines.h"
39
 
 
40
 
 
41
 
struct st_framebuffer *
42
 
st_create_framebuffer( const __GLcontextModes *visual,
43
 
                       enum pipe_format colorFormat,
44
 
                       enum pipe_format depthFormat,
45
 
                       enum pipe_format stencilFormat,
46
 
                       uint width, uint height,
47
 
                       void *private)
48
 
{
49
 
   struct st_framebuffer *stfb = ST_CALLOC_STRUCT(st_framebuffer);
50
 
   if (stfb) {
51
 
      int samples = st_get_msaa();
52
 
      int i;
53
 
 
54
 
      if (visual->sampleBuffers)
55
 
         samples = visual->samples;
56
 
 
57
 
      _mesa_initialize_window_framebuffer(&stfb->Base, visual);
58
 
 
59
 
      if (visual->doubleBufferMode) {
60
 
         struct gl_renderbuffer *rb
61
 
            = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
62
 
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
63
 
      }
64
 
      else {
65
 
         /* Only allocate front buffer right now if we're single buffered.
66
 
          * If double-buffered, allocate front buffer on demand later.
67
 
          * See check_create_front_buffers() and st_set_framebuffer_surface().
68
 
          */
69
 
         struct gl_renderbuffer *rb
70
 
            = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
71
 
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
72
 
      }
73
 
 
74
 
      if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) {
75
 
         /* combined depth/stencil buffer */
76
 
         struct gl_renderbuffer *depthStencilRb
77
 
            = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
78
 
         /* note: bind RB to two attachment points */
79
 
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthStencilRb);
80
 
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, depthStencilRb);
81
 
      }
82
 
      else {
83
 
         /* separate depth and/or stencil */
84
 
 
85
 
         if (visual->depthBits == 32) {
86
 
            /* 32-bit depth buffer */
87
 
            struct gl_renderbuffer *depthRb
88
 
               = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
89
 
            _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
90
 
         }
91
 
         else if (visual->depthBits == 24) {
92
 
            /* 24-bit depth buffer, ignore stencil bits */
93
 
            struct gl_renderbuffer *depthRb
94
 
               = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
95
 
            _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
96
 
         }
97
 
         else if (visual->depthBits > 0) {
98
 
            /* 16-bit depth buffer */
99
 
            struct gl_renderbuffer *depthRb
100
 
               = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
101
 
            _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
102
 
         }
103
 
 
104
 
         if (visual->stencilBits > 0) {
105
 
            /* 8-bit stencil */
106
 
            struct gl_renderbuffer *stencilRb
107
 
               = st_new_renderbuffer_fb(stencilFormat, samples, FALSE);
108
 
            _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, stencilRb);
109
 
         }
110
 
      }
111
 
 
112
 
      if (visual->accumRedBits > 0) {
113
 
         /* 16-bit/channel accum */
114
 
         /* TODO: query the pipe screen for accumulation buffer format support */
115
 
         struct gl_renderbuffer *accumRb
116
 
            = st_new_renderbuffer_fb(PIPE_FORMAT_R16G16B16A16_SNORM, 0, TRUE);
117
 
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb);
118
 
      }
119
 
 
120
 
      for (i = 0; i < visual->numAuxBuffers; i++) {
121
 
         struct gl_renderbuffer *aux
122
 
            = st_new_renderbuffer_fb(colorFormat, 0, FALSE);
123
 
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_AUX0 + i, aux);
124
 
      }
125
 
 
126
 
      stfb->Base.Initialized = GL_TRUE;
127
 
      stfb->InitWidth = width;
128
 
      stfb->InitHeight = height;
129
 
      stfb->Private = private;
130
 
   }
131
 
   return stfb;
132
 
}
133
 
 
134
 
 
135
 
void st_resize_framebuffer( struct st_framebuffer *stfb,
136
 
                            uint width, uint height )
137
 
{
138
 
   if (stfb->Base.Width != width || stfb->Base.Height != height) {
139
 
      GET_CURRENT_CONTEXT(ctx);
140
 
      if (ctx) {
141
 
         _mesa_check_init_viewport(ctx, width, height);
142
 
 
143
 
         _mesa_resize_framebuffer(ctx, &stfb->Base, width, height);
144
 
 
145
 
         assert(stfb->Base.Width == width);
146
 
         assert(stfb->Base.Height == height);
147
 
      }
148
 
   }
149
 
}
150
 
 
151
 
 
152
 
void st_unreference_framebuffer( struct st_framebuffer *stfb )
153
 
{
154
 
   _mesa_reference_framebuffer((struct gl_framebuffer **) &stfb, NULL);
155
 
}
156
 
 
157
 
 
158
 
 
159
 
/**
160
 
 * Set/replace a framebuffer surface.
161
 
 * The user of the state tracker can use this instead of
162
 
 * st_resize_framebuffer() to provide new surfaces when a window is resized.
163
 
 * \param surfIndex  an ST_SURFACE_x index
164
 
 */
165
 
void
166
 
st_set_framebuffer_surface(struct st_framebuffer *stfb,
167
 
                           uint surfIndex, struct pipe_surface *surf)
168
 
{
169
 
   GET_CURRENT_CONTEXT(ctx);
170
 
   struct st_renderbuffer *strb;
171
 
 
172
 
   /* sanity checks */
173
 
   assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
174
 
   assert(ST_SURFACE_BACK_LEFT == BUFFER_BACK_LEFT);
175
 
   assert(ST_SURFACE_FRONT_RIGHT == BUFFER_FRONT_RIGHT);
176
 
   assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
177
 
   assert(ST_SURFACE_DEPTH == BUFFER_DEPTH);
178
 
 
179
 
   assert(surfIndex < BUFFER_COUNT);
180
 
 
181
 
   strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
182
 
 
183
 
   if (!strb) {
184
 
      /* create new renderbuffer for this surface now */
185
 
      const GLuint numSamples = stfb->Base.Visual.samples;
186
 
      struct gl_renderbuffer *rb =
187
 
         st_new_renderbuffer_fb(surf->format, numSamples, FALSE);
188
 
      if (!rb) {
189
 
         /* out of memory */
190
 
         _mesa_warning(ctx, "Out of memory allocating renderbuffer");
191
 
         return;
192
 
      }
193
 
      _mesa_add_renderbuffer(&stfb->Base, surfIndex, rb);
194
 
      strb = st_renderbuffer(rb);
195
 
   }
196
 
 
197
 
   /* replace the renderbuffer's surface/texture pointers */
198
 
   pipe_surface_reference( &strb->surface, surf );
199
 
   pipe_texture_reference( &strb->texture, surf->texture );
200
 
 
201
 
   if (ctx) {
202
 
      /* If ctx isn't set, we've likely not made current yet.
203
 
       * But when we do, we need to start setting this dirty bit
204
 
       * to ensure the renderbuffer attachements are up-to-date
205
 
       * via update_framebuffer.
206
 
       * Core Mesa's state validation will update the parent framebuffer's
207
 
       * size info, etc.
208
 
       */
209
 
      ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
210
 
      ctx->NewState |= _NEW_BUFFERS;
211
 
   }
212
 
 
213
 
   /* update renderbuffer's width/height */
214
 
   strb->Base.Width = surf->width;
215
 
   strb->Base.Height = surf->height;
216
 
}
217
 
 
218
 
 
219
 
 
220
 
/**
221
 
 * Return the pipe_surface for the given renderbuffer.
222
 
 */
223
 
int
224
 
st_get_framebuffer_surface(struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
225
 
{
226
 
   struct st_renderbuffer *strb;
227
 
 
228
 
   assert(surfIndex <= ST_SURFACE_DEPTH);
229
 
 
230
 
   /* sanity checks, ST tokens should match Mesa tokens */
231
 
   assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
232
 
   assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
233
 
 
234
 
   strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
235
 
   if (strb) {
236
 
      *surface = strb->surface;
237
 
      return GL_TRUE;
238
 
   }
239
 
 
240
 
   *surface = NULL;
241
 
   return GL_FALSE;
242
 
}
243
 
 
244
 
int
245
 
st_get_framebuffer_texture(struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
246
 
{
247
 
   struct st_renderbuffer *strb;
248
 
 
249
 
   assert(surfIndex <= ST_SURFACE_DEPTH);
250
 
 
251
 
   /* sanity checks, ST tokens should match Mesa tokens */
252
 
   assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
253
 
   assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
254
 
 
255
 
   strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
256
 
   if (strb) {
257
 
      *texture = strb->texture;
258
 
      return GL_TRUE;
259
 
   }
260
 
 
261
 
   *texture = NULL;
262
 
   return GL_FALSE;
263
 
}
264
 
 
265
 
/**
266
 
 * This function is to be called prior to SwapBuffers on the given
267
 
 * framebuffer.  It checks if the current context is bound to the framebuffer
268
 
 * and flushes rendering if needed.
269
 
 */
270
 
void
271
 
st_notify_swapbuffers(struct st_framebuffer *stfb)
272
 
{
273
 
   GET_CURRENT_CONTEXT(ctx);
274
 
 
275
 
   if (ctx && ctx->DrawBuffer == &stfb->Base) {
276
 
      st_flush( ctx->st, 
277
 
                PIPE_FLUSH_RENDER_CACHE | 
278
 
                PIPE_FLUSH_SWAPBUFFERS |
279
 
                PIPE_FLUSH_FRAME,
280
 
                NULL );
281
 
      if (st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer))
282
 
         ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
283
 
   }
284
 
}
285
 
 
286
 
 
287
 
/**
288
 
 * Swap the front/back color buffers.  Exchange the front/back pointers
289
 
 * and update some derived state.
290
 
 * No need to call st_notify_swapbuffers() first.
291
 
 *
292
 
 * For a single-buffered framebuffer, no swap occurs, but we still return
293
 
 * the pointer(s) to the front color buffer(s).
294
 
 *
295
 
 * \param front_left  returns pointer to front-left renderbuffer after swap
296
 
 * \param front_right  returns pointer to front-right renderbuffer after swap
297
 
 */
298
 
void
299
 
st_swapbuffers(struct st_framebuffer *stfb,
300
 
               struct pipe_surface **front_left,
301
 
               struct pipe_surface **front_right)
302
 
{
303
 
   struct gl_framebuffer *fb = &stfb->Base;
304
 
 
305
 
   GET_CURRENT_CONTEXT(ctx);
306
 
 
307
 
   if (ctx && ctx->DrawBuffer == &stfb->Base) {
308
 
      st_flush( ctx->st, 
309
 
                PIPE_FLUSH_RENDER_CACHE | 
310
 
                PIPE_FLUSH_SWAPBUFFERS |
311
 
                PIPE_FLUSH_FRAME,
312
 
                NULL );
313
 
   }
314
 
 
315
 
   if (!fb->Visual.doubleBufferMode) {
316
 
      /* single buffer mode - return pointers to front surfaces */
317
 
      if (front_left) {
318
 
         struct st_renderbuffer *strb =
319
 
            st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
320
 
         *front_left = strb->surface;
321
 
      }
322
 
      if (front_right) {
323
 
         struct st_renderbuffer *strb =
324
 
            st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
325
 
         *front_right = strb ? strb->surface : NULL;
326
 
      }
327
 
      return;
328
 
   }
329
 
 
330
 
   /* swap left buffers */
331
 
   if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
332
 
       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) {
333
 
      struct gl_renderbuffer *rbTemp;
334
 
      rbTemp = fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
335
 
      fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer =
336
 
         fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
337
 
      fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer = rbTemp;
338
 
      if (front_left) {
339
 
         struct st_renderbuffer *strb =
340
 
            st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
341
 
         *front_left = strb->surface;
342
 
      }
343
 
      /* mark back buffer contents as undefined */
344
 
      {
345
 
         struct st_renderbuffer *back =
346
 
            st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
347
 
         back->defined = GL_FALSE;
348
 
      }
349
 
   }
350
 
   else {
351
 
      /* no front buffer, display the back buffer */
352
 
      if (front_left) {
353
 
         struct st_renderbuffer *strb =
354
 
            st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
355
 
         *front_left = strb->surface;
356
 
      }
357
 
   }
358
 
 
359
 
   /* swap right buffers (for stereo) */
360
 
   if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
361
 
       fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) {
362
 
      struct gl_renderbuffer *rbTemp;
363
 
      rbTemp = fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer;
364
 
      fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer =
365
 
         fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer;
366
 
      fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer = rbTemp;
367
 
      if (front_right) {
368
 
         struct st_renderbuffer *strb =
369
 
            st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
370
 
         *front_right = strb->surface;
371
 
      }
372
 
      /* mark back buffer contents as undefined */
373
 
      {
374
 
         struct st_renderbuffer *back =
375
 
            st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
376
 
         back->defined = GL_FALSE;
377
 
      }
378
 
   }
379
 
   else {
380
 
      /* no front right buffer, display back right buffer (if exists) */
381
 
      if (front_right) {
382
 
         struct st_renderbuffer *strb =
383
 
            st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
384
 
         *front_right = strb ? strb->surface : NULL;
385
 
      }
386
 
   }
387
 
 
388
 
   /* Update the _ColorDrawBuffers[] array and _ColorReadBuffer pointer */
389
 
   _mesa_update_framebuffer(ctx);
390
 
 
391
 
   /* Make sure we draw into the new back surface */
392
 
   st_invalidate_state(ctx, _NEW_BUFFERS);
393
 
}
394
 
 
395
 
 
396
 
void *st_framebuffer_private( struct st_framebuffer *stfb )
397
 
{
398
 
   return stfb->Private;
399
 
}
400
 
 
401
 
void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
402
 
                                    uint *width,
403
 
                                    uint *height)
404
 
{
405
 
   *width = stfb->Base.Width;
406
 
   *height = stfb->Base.Height;
407
 
}