nouveau_fbo.c revision 1933e97034a1774e37268035f67ca5973220e8c6
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#include "main/mfeatures.h" 36 37static GLboolean 38set_renderbuffer_format(struct gl_renderbuffer *rb, GLenum internalFormat) 39{ 40 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; 41 42 rb->InternalFormat = internalFormat; 43 44 switch (internalFormat) { 45 case GL_RGB: 46 case GL_RGB8: 47 rb->_BaseFormat = GL_RGB; 48 rb->Format = MESA_FORMAT_XRGB8888; 49 rb->DataType = GL_UNSIGNED_BYTE; 50 s->cpp = 4; 51 break; 52 case GL_RGBA: 53 case GL_RGBA8: 54 rb->_BaseFormat = GL_RGBA; 55 rb->Format = MESA_FORMAT_ARGB8888; 56 rb->DataType = GL_UNSIGNED_BYTE; 57 s->cpp = 4; 58 break; 59 case GL_RGB5: 60 rb->_BaseFormat = GL_RGB; 61 rb->Format = MESA_FORMAT_RGB565; 62 rb->DataType = GL_UNSIGNED_BYTE; 63 s->cpp = 2; 64 break; 65 case GL_DEPTH_COMPONENT16: 66 rb->_BaseFormat = GL_DEPTH_COMPONENT; 67 rb->Format = MESA_FORMAT_Z16; 68 rb->DataType = GL_UNSIGNED_SHORT; 69 s->cpp = 2; 70 break; 71 case GL_DEPTH_COMPONENT: 72 case GL_DEPTH_COMPONENT24: 73 case GL_STENCIL_INDEX8_EXT: 74 case GL_DEPTH24_STENCIL8_EXT: 75 rb->_BaseFormat = GL_DEPTH_STENCIL; 76 rb->Format = MESA_FORMAT_Z24_S8; 77 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 78 s->cpp = 4; 79 break; 80 default: 81 return GL_FALSE; 82 } 83 84 s->format = rb->Format; 85 86 return GL_TRUE; 87} 88 89static GLboolean 90nouveau_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 91 GLenum internalFormat, 92 GLuint width, GLuint height) 93{ 94 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; 95 96 if (!set_renderbuffer_format(rb, internalFormat)) 97 return GL_FALSE; 98 99 rb->Width = width; 100 rb->Height = height; 101 102 nouveau_surface_alloc(ctx, s, TILED, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 103 rb->Format, width, height); 104 105 context_dirty(ctx, FRAMEBUFFER); 106 return GL_TRUE; 107} 108 109static void 110nouveau_renderbuffer_del(struct gl_renderbuffer *rb) 111{ 112 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; 113 114 nouveau_surface_ref(NULL, s); 115 FREE(rb); 116} 117 118static struct gl_renderbuffer * 119nouveau_renderbuffer_new(struct gl_context *ctx, GLuint name) 120{ 121 struct gl_renderbuffer *rb; 122 123 rb = (struct gl_renderbuffer *) 124 CALLOC_STRUCT(nouveau_renderbuffer); 125 if (!rb) 126 return NULL; 127 128 _mesa_init_renderbuffer(rb, name); 129 130 rb->AllocStorage = nouveau_renderbuffer_storage; 131 rb->Delete = nouveau_renderbuffer_del; 132 133 return rb; 134} 135 136static GLboolean 137nouveau_renderbuffer_dri_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 138 GLenum internalFormat, 139 GLuint width, GLuint height) 140{ 141 if (!set_renderbuffer_format(rb, internalFormat)) 142 return GL_FALSE; 143 144 rb->Width = width; 145 rb->Height = height; 146 147 return GL_TRUE; 148} 149 150struct gl_renderbuffer * 151nouveau_renderbuffer_dri_new(GLenum format, __DRIdrawable *drawable) 152{ 153 struct gl_renderbuffer *rb; 154 155 rb = nouveau_renderbuffer_new(NULL, 0); 156 if (!rb) 157 return NULL; 158 159 rb->AllocStorage = nouveau_renderbuffer_dri_storage; 160 161 if (!set_renderbuffer_format(rb, format)) { 162 nouveau_renderbuffer_del(rb); 163 return NULL; 164 } 165 166 return rb; 167} 168 169static struct gl_framebuffer * 170nouveau_framebuffer_new(struct gl_context *ctx, GLuint name) 171{ 172 struct nouveau_framebuffer *nfb; 173 174 nfb = CALLOC_STRUCT(nouveau_framebuffer); 175 if (!nfb) 176 return NULL; 177 178 _mesa_initialize_user_framebuffer(&nfb->base, name); 179 180 return &nfb->base; 181} 182 183struct gl_framebuffer * 184nouveau_framebuffer_dri_new(const struct gl_config *visual) 185{ 186 struct nouveau_framebuffer *nfb; 187 188 nfb = CALLOC_STRUCT(nouveau_framebuffer); 189 if (!nfb) 190 return NULL; 191 192 _mesa_initialize_window_framebuffer(&nfb->base, visual); 193 nfb->need_front = !visual->doubleBufferMode; 194 195 return &nfb->base; 196} 197 198static void 199nouveau_bind_framebuffer(struct gl_context *ctx, GLenum target, 200 struct gl_framebuffer *dfb, 201 struct gl_framebuffer *rfb) 202{ 203 context_dirty(ctx, FRAMEBUFFER); 204} 205 206static void 207nouveau_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 208 GLenum attachment, struct gl_renderbuffer *rb) 209{ 210 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 211 212 context_dirty(ctx, FRAMEBUFFER); 213} 214 215static GLenum 216get_tex_format(struct gl_texture_image *ti) 217{ 218 switch (ti->TexFormat) { 219 case MESA_FORMAT_ARGB8888: 220 return GL_RGBA8; 221 case MESA_FORMAT_XRGB8888: 222 return GL_RGB8; 223 case MESA_FORMAT_RGB565: 224 return GL_RGB5; 225 default: 226 return GL_NONE; 227 } 228} 229 230static void 231nouveau_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, 232 struct gl_renderbuffer_attachment *att) 233{ 234 struct gl_renderbuffer *rb = att->Renderbuffer; 235 struct gl_texture_image *ti = 236 att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 237 238 /* Allocate a renderbuffer object for the texture if we 239 * haven't already done so. */ 240 if (!rb) { 241 rb = nouveau_renderbuffer_new(ctx, ~0); 242 assert(rb); 243 244 rb->AllocStorage = NULL; 245 _mesa_reference_renderbuffer(&att->Renderbuffer, rb); 246 } 247 248 /* Update the renderbuffer fields from the texture. */ 249 set_renderbuffer_format(rb, get_tex_format(ti)); 250 rb->Width = ti->Width; 251 rb->Height = ti->Height; 252 nouveau_surface_ref(&to_nouveau_teximage(ti)->surface, 253 &to_nouveau_renderbuffer(rb)->surface); 254 255 context_dirty(ctx, FRAMEBUFFER); 256} 257 258static void 259nouveau_finish_render_texture(struct gl_context *ctx, 260 struct gl_renderbuffer_attachment *att) 261{ 262 texture_dirty(att->Texture); 263} 264 265void 266nouveau_fbo_functions_init(struct dd_function_table *functions) 267{ 268#if FEATURE_EXT_framebuffer_object 269 functions->NewFramebuffer = nouveau_framebuffer_new; 270 functions->NewRenderbuffer = nouveau_renderbuffer_new; 271 functions->BindFramebuffer = nouveau_bind_framebuffer; 272 functions->FramebufferRenderbuffer = nouveau_framebuffer_renderbuffer; 273 functions->RenderTexture = nouveau_render_texture; 274 functions->FinishRenderTexture = nouveau_finish_render_texture; 275#endif 276} 277