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