Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / common / drirenderbuffer.c
1
2 #include "main/mtypes.h"
3 #include "main/formats.h"
4 #include "main/framebuffer.h"
5 #include "main/renderbuffer.h"
6 #include "main/imports.h"
7 #include "drirenderbuffer.h"
8
9
10 /**
11 * This will get called when a window (gl_framebuffer) is resized (probably
12 * via driUpdateFramebufferSize(), below).
13 * Just update width, height and internal format fields for now.
14 * There's usually no memory allocation above because the present
15 * DRI drivers use statically-allocated full-screen buffers. If that's not
16 * the case for a DRI driver, a different AllocStorage method should
17 * be used.
18 */
19 static GLboolean
20 driRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb,
21 GLenum internalFormat, GLuint width, GLuint height)
22 {
23 rb->Width = width;
24 rb->Height = height;
25 rb->InternalFormat = internalFormat;
26 return GL_TRUE;
27 }
28
29
30 static void
31 driDeleteRenderbuffer(struct gl_renderbuffer *rb)
32 {
33 /* don't free rb->Data Chances are it's a memory mapped region for
34 * the dri drivers.
35 */
36 _mesa_free(rb);
37 }
38
39
40 /**
41 * Allocate a new driRenderbuffer object.
42 * Individual drivers are free to implement different versions of
43 * this function.
44 *
45 * At this time, this function can only be used for window-system
46 * renderbuffers, not user-created RBOs.
47 *
48 * \param format Either GL_RGBA, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
49 * GL_DEPTH_COMPONENT32, or GL_STENCIL_INDEX8_EXT (for now).
50 * \param addr address in main memory of the buffer. Probably a memory
51 * mapped region.
52 * \param cpp chars or bytes per pixel
53 * \param offset start of renderbuffer with respect to start of framebuffer
54 * \param pitch pixels per row
55 */
56 driRenderbuffer *
57 driNewRenderbuffer(gl_format format, GLvoid *addr,
58 GLint cpp, GLint offset, GLint pitch,
59 __DRIdrawable *dPriv)
60 {
61 driRenderbuffer *drb;
62
63 assert(format == GL_RGBA ||
64 format == GL_RGB5 ||
65 format == GL_RGBA8 ||
66 format == GL_DEPTH_COMPONENT16 ||
67 format == GL_DEPTH_COMPONENT24 ||
68 format == GL_DEPTH_COMPONENT32 ||
69 format == GL_STENCIL_INDEX8_EXT);
70
71 assert(cpp > 0);
72 assert(pitch > 0);
73
74 drb = _mesa_calloc(sizeof(driRenderbuffer));
75 if (drb) {
76 const GLuint name = 0;
77
78 _mesa_init_renderbuffer(&drb->Base, name);
79
80 /* Make sure we're using a null-valued GetPointer routine */
81 assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL);
82
83 switch (format) {
84 case MESA_FORMAT_ARGB8888:
85 if (cpp == 2) {
86 /* override format */
87 format = MESA_FORMAT_RGB565;
88 }
89 drb->Base.DataType = GL_UNSIGNED_BYTE;
90 break;
91 case MESA_FORMAT_Z16:
92 /* Depth */
93 /* we always Get/Put 32-bit Z values */
94 drb->Base.DataType = GL_UNSIGNED_INT;
95 assert(cpp == 2);
96 break;
97 case MESA_FORMAT_Z32:
98 /* Depth */
99 /* we always Get/Put 32-bit Z values */
100 drb->Base.DataType = GL_UNSIGNED_INT;
101 assert(cpp == 4);
102 break;
103 case MESA_FORMAT_Z24_S8:
104 drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
105 assert(cpp == 4);
106 break;
107 case MESA_FORMAT_S8_Z24:
108 drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
109 assert(cpp == 4);
110 break;
111 case MESA_FORMAT_S8:
112 /* Stencil */
113 drb->Base.DataType = GL_UNSIGNED_BYTE;
114 break;
115 default:
116 _mesa_problem(NULL, "Bad format 0x%x in driNewRenderbuffer", format);
117 return NULL;
118 }
119
120 drb->Base.Format = format;
121
122 drb->Base.InternalFormat =
123 drb->Base._BaseFormat = _mesa_get_format_base_format(format);
124
125 drb->Base.AllocStorage = driRenderbufferStorage;
126 drb->Base.Delete = driDeleteRenderbuffer;
127
128 drb->Base.Data = addr;
129
130 /* DRI renderbuffer-specific fields: */
131 drb->dPriv = dPriv;
132 drb->offset = offset;
133 drb->pitch = pitch;
134 drb->cpp = cpp;
135
136 /* may be changed if page flipping is active: */
137 drb->flippedOffset = offset;
138 drb->flippedPitch = pitch;
139 drb->flippedData = addr;
140 }
141 return drb;
142 }
143
144
145 /**
146 * Update the front and back renderbuffers' flippedPitch/Offset/Data fields.
147 * If stereo, flip both the left and right pairs.
148 * This is used when we do double buffering via page flipping.
149 * \param fb the framebuffer we're page flipping
150 * \param flipped if true, set flipped values, else set non-flipped values
151 */
152 void
153 driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped)
154 {
155 const GLuint count = fb->Visual.stereoMode ? 2 : 1;
156 GLuint lr; /* left or right */
157
158 /* we shouldn't really call this function if single-buffered, but
159 * play it safe.
160 */
161 if (!fb->Visual.doubleBufferMode)
162 return;
163
164 for (lr = 0; lr < count; lr++) {
165 GLuint frontBuf = (lr == 0) ? BUFFER_FRONT_LEFT : BUFFER_FRONT_RIGHT;
166 GLuint backBuf = (lr == 0) ? BUFFER_BACK_LEFT : BUFFER_BACK_RIGHT;
167 driRenderbuffer *front_drb
168 = (driRenderbuffer *) fb->Attachment[frontBuf].Renderbuffer;
169 driRenderbuffer *back_drb
170 = (driRenderbuffer *) fb->Attachment[backBuf].Renderbuffer;
171
172 if (flipped) {
173 front_drb->flippedOffset = back_drb->offset;
174 front_drb->flippedPitch = back_drb->pitch;
175 front_drb->flippedData = back_drb->Base.Data;
176 back_drb->flippedOffset = front_drb->offset;
177 back_drb->flippedPitch = front_drb->pitch;
178 back_drb->flippedData = front_drb->Base.Data;
179 }
180 else {
181 front_drb->flippedOffset = front_drb->offset;
182 front_drb->flippedPitch = front_drb->pitch;
183 front_drb->flippedData = front_drb->Base.Data;
184 back_drb->flippedOffset = back_drb->offset;
185 back_drb->flippedPitch = back_drb->pitch;
186 back_drb->flippedData = back_drb->Base.Data;
187 }
188 }
189 }
190
191
192 /**
193 * Check that the gl_framebuffer associated with dPriv is the right size.
194 * Resize the gl_framebuffer if needed.
195 * It's expected that the dPriv->driverPrivate member points to a
196 * gl_framebuffer object.
197 */
198 void
199 driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawable *dPriv)
200 {
201 struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
202 if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
203 ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
204 /* if the driver needs the hw lock for ResizeBuffers, the drawable
205 might have changed again by now */
206 assert(fb->Width == dPriv->w);
207 assert(fb->Height == dPriv->h);
208 }
209 }