Merge branch 'master' into gallium-sampler-view
[mesa.git] / src / mesa / drivers / dri / common / drirenderbuffer.c
1
2 #include "main/mtypes.h"
3 #include "main/formats.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 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(gl_format format, GLvoid *addr,
57 GLint cpp, GLint offset, GLint pitch,
58 __DRIdrawable *dPriv)
59 {
60 driRenderbuffer *drb;
61
62 assert(cpp > 0);
63 assert(pitch > 0);
64
65 drb = calloc(1, sizeof(driRenderbuffer));
66 if (drb) {
67 const GLuint name = 0;
68
69 _mesa_init_renderbuffer(&drb->Base, name);
70
71 /* Make sure we're using a null-valued GetPointer routine */
72 assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL);
73
74 switch (format) {
75 case MESA_FORMAT_ARGB8888:
76 if (cpp == 2) {
77 /* override format */
78 format = MESA_FORMAT_RGB565;
79 }
80 drb->Base.DataType = GL_UNSIGNED_BYTE;
81 break;
82 case MESA_FORMAT_Z16:
83 /* Depth */
84 /* we always Get/Put 32-bit Z values */
85 drb->Base.DataType = GL_UNSIGNED_INT;
86 assert(cpp == 2);
87 break;
88 case MESA_FORMAT_Z32:
89 /* Depth */
90 /* we always Get/Put 32-bit Z values */
91 drb->Base.DataType = GL_UNSIGNED_INT;
92 assert(cpp == 4);
93 break;
94 case MESA_FORMAT_Z24_S8:
95 drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
96 assert(cpp == 4);
97 break;
98 case MESA_FORMAT_S8_Z24:
99 drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
100 assert(cpp == 4);
101 break;
102 case MESA_FORMAT_S8:
103 /* Stencil */
104 drb->Base.DataType = GL_UNSIGNED_BYTE;
105 break;
106 default:
107 _mesa_problem(NULL, "Bad format 0x%x in driNewRenderbuffer", format);
108 return NULL;
109 }
110
111 drb->Base.Format = format;
112
113 drb->Base.InternalFormat =
114 drb->Base._BaseFormat = _mesa_get_format_base_format(format);
115
116 drb->Base.AllocStorage = driRenderbufferStorage;
117 drb->Base.Delete = driDeleteRenderbuffer;
118
119 drb->Base.Data = addr;
120
121 /* DRI renderbuffer-specific fields: */
122 drb->dPriv = dPriv;
123 drb->offset = offset;
124 drb->pitch = pitch;
125 drb->cpp = cpp;
126
127 /* may be changed if page flipping is active: */
128 drb->flippedOffset = offset;
129 drb->flippedPitch = pitch;
130 drb->flippedData = addr;
131 }
132 return drb;
133 }
134
135
136 /**
137 * Update the front and back renderbuffers' flippedPitch/Offset/Data fields.
138 * If stereo, flip both the left and right pairs.
139 * This is used when we do double buffering via page flipping.
140 * \param fb the framebuffer we're page flipping
141 * \param flipped if true, set flipped values, else set non-flipped values
142 */
143 void
144 driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped)
145 {
146 const GLuint count = fb->Visual.stereoMode ? 2 : 1;
147 GLuint lr; /* left or right */
148
149 /* we shouldn't really call this function if single-buffered, but
150 * play it safe.
151 */
152 if (!fb->Visual.doubleBufferMode)
153 return;
154
155 for (lr = 0; lr < count; lr++) {
156 GLuint frontBuf = (lr == 0) ? BUFFER_FRONT_LEFT : BUFFER_FRONT_RIGHT;
157 GLuint backBuf = (lr == 0) ? BUFFER_BACK_LEFT : BUFFER_BACK_RIGHT;
158 driRenderbuffer *front_drb
159 = (driRenderbuffer *) fb->Attachment[frontBuf].Renderbuffer;
160 driRenderbuffer *back_drb
161 = (driRenderbuffer *) fb->Attachment[backBuf].Renderbuffer;
162
163 if (flipped) {
164 front_drb->flippedOffset = back_drb->offset;
165 front_drb->flippedPitch = back_drb->pitch;
166 front_drb->flippedData = back_drb->Base.Data;
167 back_drb->flippedOffset = front_drb->offset;
168 back_drb->flippedPitch = front_drb->pitch;
169 back_drb->flippedData = front_drb->Base.Data;
170 }
171 else {
172 front_drb->flippedOffset = front_drb->offset;
173 front_drb->flippedPitch = front_drb->pitch;
174 front_drb->flippedData = front_drb->Base.Data;
175 back_drb->flippedOffset = back_drb->offset;
176 back_drb->flippedPitch = back_drb->pitch;
177 back_drb->flippedData = back_drb->Base.Data;
178 }
179 }
180 }
181
182
183 /**
184 * Check that the gl_framebuffer associated with dPriv is the right size.
185 * Resize the gl_framebuffer if needed.
186 * It's expected that the dPriv->driverPrivate member points to a
187 * gl_framebuffer object.
188 */
189 void
190 driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawable *dPriv)
191 {
192 struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
193 if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
194 ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
195 /* if the driver needs the hw lock for ResizeBuffers, the drawable
196 might have changed again by now */
197 assert(fb->Width == dPriv->w);
198 assert(fb->Height == dPriv->h);
199 }
200 }