mesa: Change many Type A MESA_FORMATs to meet naming standard
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_fbo.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_fbo.h"
29 #include "nouveau_context.h"
30 #include "nouveau_texture.h"
31
32 #include "main/framebuffer.h"
33 #include "main/renderbuffer.h"
34 #include "main/fbobject.h"
35
36 static GLboolean
37 set_renderbuffer_format(struct gl_renderbuffer *rb, GLenum internalFormat)
38 {
39 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
40
41 rb->InternalFormat = internalFormat;
42
43 switch (internalFormat) {
44 case GL_RGB:
45 case GL_RGB8:
46 rb->_BaseFormat = GL_RGB;
47 rb->Format = MESA_FORMAT_B8G8R8X8_UNORM;
48 s->cpp = 4;
49 break;
50 case GL_RGBA:
51 case GL_RGBA8:
52 rb->_BaseFormat = GL_RGBA;
53 rb->Format = MESA_FORMAT_B8G8R8A8_UNORM;
54 s->cpp = 4;
55 break;
56 case GL_RGB5:
57 rb->_BaseFormat = GL_RGB;
58 rb->Format = MESA_FORMAT_RGB565;
59 s->cpp = 2;
60 break;
61 case GL_DEPTH_COMPONENT16:
62 rb->_BaseFormat = GL_DEPTH_COMPONENT;
63 rb->Format = MESA_FORMAT_Z_UNORM16;
64 s->cpp = 2;
65 break;
66 case GL_DEPTH_COMPONENT:
67 case GL_DEPTH_COMPONENT24:
68 case GL_STENCIL_INDEX8_EXT:
69 case GL_DEPTH24_STENCIL8_EXT:
70 rb->_BaseFormat = GL_DEPTH_STENCIL;
71 rb->Format = MESA_FORMAT_Z24_S8;
72 s->cpp = 4;
73 break;
74 default:
75 return GL_FALSE;
76 }
77
78 s->format = rb->Format;
79
80 return GL_TRUE;
81 }
82
83 static GLboolean
84 nouveau_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
85 GLenum internalFormat,
86 GLuint width, GLuint height)
87 {
88 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
89
90 if (!set_renderbuffer_format(rb, internalFormat))
91 return GL_FALSE;
92
93 rb->Width = width;
94 rb->Height = height;
95
96 nouveau_surface_alloc(ctx, s, TILED, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP,
97 rb->Format, width, height);
98
99 context_dirty(ctx, FRAMEBUFFER);
100 return GL_TRUE;
101 }
102
103 static void
104 nouveau_renderbuffer_del(struct gl_context *ctx, struct gl_renderbuffer *rb)
105 {
106 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
107
108 nouveau_surface_ref(NULL, s);
109 _mesa_delete_renderbuffer(ctx, rb);
110 }
111
112 static struct gl_renderbuffer *
113 nouveau_renderbuffer_new(struct gl_context *ctx, GLuint name)
114 {
115 struct gl_renderbuffer *rb;
116
117 rb = (struct gl_renderbuffer *)
118 CALLOC_STRUCT(nouveau_renderbuffer);
119 if (!rb)
120 return NULL;
121
122 _mesa_init_renderbuffer(rb, name);
123
124 rb->AllocStorage = nouveau_renderbuffer_storage;
125 rb->Delete = nouveau_renderbuffer_del;
126
127 return rb;
128 }
129
130 static void
131 nouveau_renderbuffer_map(struct gl_context *ctx,
132 struct gl_renderbuffer *rb,
133 GLuint x, GLuint y, GLuint w, GLuint h,
134 GLbitfield mode,
135 GLubyte **out_map,
136 GLint *out_stride)
137 {
138 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
139 GLubyte *map;
140 int stride;
141 int flags = 0;
142
143 if (mode & GL_MAP_READ_BIT)
144 flags |= NOUVEAU_BO_RD;
145 if (mode & GL_MAP_WRITE_BIT)
146 flags |= NOUVEAU_BO_WR;
147
148 nouveau_bo_map(s->bo, flags, context_client(ctx));
149
150 map = s->bo->map;
151 stride = s->pitch;
152
153 if (rb->Name == 0) {
154 map += stride * (rb->Height - 1);
155 stride = -stride;
156 }
157
158 map += x * s->cpp;
159 map += (int)y * stride;
160
161 *out_map = map;
162 *out_stride = stride;
163 }
164
165 static void
166 nouveau_renderbuffer_unmap(struct gl_context *ctx,
167 struct gl_renderbuffer *rb)
168 {
169 }
170
171 static GLboolean
172 nouveau_renderbuffer_dri_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
173 GLenum internalFormat,
174 GLuint width, GLuint height)
175 {
176 if (!set_renderbuffer_format(rb, internalFormat))
177 return GL_FALSE;
178
179 rb->Width = width;
180 rb->Height = height;
181
182 return GL_TRUE;
183 }
184
185 struct gl_renderbuffer *
186 nouveau_renderbuffer_dri_new(GLenum format, __DRIdrawable *drawable)
187 {
188 struct gl_renderbuffer *rb;
189
190 rb = nouveau_renderbuffer_new(NULL, 0);
191 if (!rb)
192 return NULL;
193
194 rb->AllocStorage = nouveau_renderbuffer_dri_storage;
195
196 if (!set_renderbuffer_format(rb, format)) {
197 nouveau_renderbuffer_del(NULL, rb);
198 return NULL;
199 }
200
201 return rb;
202 }
203
204 static struct gl_framebuffer *
205 nouveau_framebuffer_new(struct gl_context *ctx, GLuint name)
206 {
207 struct nouveau_framebuffer *nfb;
208
209 nfb = CALLOC_STRUCT(nouveau_framebuffer);
210 if (!nfb)
211 return NULL;
212
213 _mesa_initialize_user_framebuffer(&nfb->base, name);
214
215 return &nfb->base;
216 }
217
218 struct gl_framebuffer *
219 nouveau_framebuffer_dri_new(const struct gl_config *visual)
220 {
221 struct nouveau_framebuffer *nfb;
222
223 nfb = CALLOC_STRUCT(nouveau_framebuffer);
224 if (!nfb)
225 return NULL;
226
227 _mesa_initialize_window_framebuffer(&nfb->base, visual);
228 nfb->need_front = !visual->doubleBufferMode;
229
230 return &nfb->base;
231 }
232
233 static void
234 nouveau_bind_framebuffer(struct gl_context *ctx, GLenum target,
235 struct gl_framebuffer *dfb,
236 struct gl_framebuffer *rfb)
237 {
238 context_dirty(ctx, FRAMEBUFFER);
239 }
240
241 static void
242 nouveau_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
243 GLenum attachment, struct gl_renderbuffer *rb)
244 {
245 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
246
247 context_dirty(ctx, FRAMEBUFFER);
248 }
249
250 static void
251 nouveau_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
252 struct gl_renderbuffer_attachment *att)
253 {
254 struct gl_renderbuffer *rb = att->Renderbuffer;
255 struct gl_texture_image *ti = rb->TexImage;
256
257 /* Update the renderbuffer fields from the texture. */
258 nouveau_surface_ref(&to_nouveau_teximage(ti)->surface,
259 &to_nouveau_renderbuffer(rb)->surface);
260
261 context_dirty(ctx, FRAMEBUFFER);
262 }
263
264 static void
265 nouveau_finish_render_texture(struct gl_context *ctx,
266 struct gl_renderbuffer *rb)
267 {
268 texture_dirty(rb->TexImage->TexObject);
269 }
270
271 static int
272 validate_format_bpp(mesa_format format)
273 {
274 switch (format) {
275 case MESA_FORMAT_B8G8R8X8_UNORM:
276 case MESA_FORMAT_B8G8R8A8_UNORM:
277 case MESA_FORMAT_Z24_S8:
278 return 32;
279 case MESA_FORMAT_RGB565:
280 case MESA_FORMAT_Z_UNORM16:
281 return 16;
282 default:
283 return 0;
284 }
285 }
286
287 static void
288 nouveau_check_framebuffer_complete(struct gl_context *ctx,
289 struct gl_framebuffer *fb)
290 {
291 struct gl_renderbuffer_attachment *color =
292 &fb->Attachment[BUFFER_COLOR0];
293 struct gl_renderbuffer_attachment *depth =
294 &fb->Attachment[BUFFER_DEPTH];
295 int color_bpp = 0, zeta_bpp;
296
297 if (color->Type == GL_TEXTURE) {
298 color_bpp = validate_format_bpp(
299 color->Renderbuffer->TexImage->TexFormat);
300 if (!color_bpp)
301 goto err;
302 }
303
304 if (depth->Type == GL_TEXTURE) {
305 zeta_bpp = validate_format_bpp(
306 depth->Renderbuffer->TexImage->TexFormat);
307 if (!zeta_bpp)
308 goto err;
309 /* NV04/NV05 requires same bpp-ness for color/zeta */
310 if (context_chipset(ctx) < 0x10 &&
311 color_bpp && color_bpp != zeta_bpp)
312 goto err;
313 }
314
315 return;
316 err:
317 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
318 return;
319 }
320
321 void
322 nouveau_fbo_functions_init(struct dd_function_table *functions)
323 {
324 functions->NewFramebuffer = nouveau_framebuffer_new;
325 functions->NewRenderbuffer = nouveau_renderbuffer_new;
326 functions->MapRenderbuffer = nouveau_renderbuffer_map;
327 functions->UnmapRenderbuffer = nouveau_renderbuffer_unmap;
328 functions->BindFramebuffer = nouveau_bind_framebuffer;
329 functions->FramebufferRenderbuffer = nouveau_framebuffer_renderbuffer;
330 functions->RenderTexture = nouveau_render_texture;
331 functions->FinishRenderTexture = nouveau_finish_render_texture;
332 functions->ValidateFramebuffer = nouveau_check_framebuffer_complete;
333 }