nouveau_context.c revision 88a560691b904cc8eacda62d9bf80987d3c430c1
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_context.h" 29#include "nouveau_bufferobj.h" 30#include "nouveau_fbo.h" 31 32#include "main/dd.h" 33#include "main/framebuffer.h" 34#include "main/light.h" 35#include "main/state.h" 36#include "drivers/common/meta.h" 37#include "drivers/common/driverfuncs.h" 38#include "swrast/swrast.h" 39#include "vbo/vbo.h" 40#include "tnl/tnl.h" 41 42#define need_GL_EXT_framebuffer_object 43#define need_GL_EXT_fog_coord 44 45#include "main/remap_helper.h" 46 47static const struct dri_extension nouveau_extensions[] = { 48 { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, 49 { "GL_ARB_multitexture", NULL }, 50 { "GL_EXT_texture_lod_bias", NULL }, 51 { "GL_SGIS_generate_mipmap", NULL }, 52 { "GL_ARB_texture_env_combine", NULL }, 53 { "GL_ARB_texture_env_dot3", NULL }, 54 { "GL_ARB_texture_env_add", NULL }, 55 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, 56 { NULL, NULL } 57}; 58 59GLboolean 60nouveau_context_create(const __GLcontextModes *visual, __DRIcontext *dri_ctx, 61 void *share_ctx) 62{ 63 __DRIscreen *dri_screen = dri_ctx->driScreenPriv; 64 struct nouveau_screen *screen = dri_screen->private; 65 struct nouveau_context *nctx; 66 GLcontext *ctx; 67 68 ctx = screen->driver->context_create(screen, visual, share_ctx); 69 if (!ctx) 70 return GL_FALSE; 71 72 nctx = to_nouveau_context(ctx); 73 nctx->dri_context = dri_ctx; 74 dri_ctx->driverPrivate = ctx; 75 76 return GL_TRUE; 77} 78 79GLboolean 80nouveau_context_init(GLcontext *ctx, struct nouveau_screen *screen, 81 const GLvisual *visual, GLcontext *share_ctx) 82{ 83 struct nouveau_context *nctx = to_nouveau_context(ctx); 84 struct dd_function_table functions; 85 86 nctx->screen = screen; 87 nctx->fallback = HWTNL; 88 89 /* Initialize the function pointers */ 90 _mesa_init_driver_functions(&functions); 91 nouveau_driver_functions_init(&functions); 92 nouveau_bufferobj_functions_init(&functions); 93 nouveau_texture_functions_init(&functions); 94 nouveau_fbo_functions_init(&functions); 95 96 /* Initialize the mesa context */ 97 _mesa_initialize_context(ctx, visual, share_ctx, &functions, NULL); 98 99 nouveau_state_init(ctx); 100 nouveau_bo_state_init(ctx); 101 _mesa_meta_init(ctx); 102 _swrast_CreateContext(ctx); 103 _vbo_CreateContext(ctx); 104 _tnl_CreateContext(ctx); 105 nouveau_span_functions_init(ctx); 106 _mesa_allow_light_in_model(ctx, GL_FALSE); 107 108 /* Enable any supported extensions */ 109 driInitExtensions(ctx, nouveau_extensions, GL_TRUE); 110 111 return GL_TRUE; 112} 113 114void 115nouveau_context_destroy(__DRIcontext *dri_ctx) 116{ 117 struct nouveau_context *nctx = dri_ctx->driverPrivate; 118 GLcontext *ctx = &nctx->base; 119 120 if (nctx->screen->context == nctx) 121 nctx->screen->context = NULL; 122 123 _tnl_DestroyContext(ctx); 124 _vbo_DestroyContext(ctx); 125 _swrast_DestroyContext(ctx); 126 _mesa_meta_free(ctx); 127 nouveau_bo_state_destroy(ctx); 128 context_drv(ctx)->context_destroy(ctx); 129} 130 131static void 132nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, 133 unsigned int *stamp) 134{ 135 struct nouveau_context *nctx = context->driverPrivate; 136 GLcontext *ctx = &nctx->base; 137 __DRIscreen *screen = context->driScreenPriv; 138 struct gl_framebuffer *fb = drawable->driverPrivate; 139 unsigned int attachments[10]; 140 __DRIbuffer *buffers = NULL; 141 int i = 0, count, ret; 142 143 *stamp = *drawable->pStamp; 144 145 attachments[i++] = __DRI_BUFFER_FRONT_LEFT; 146 if (fb->Visual.doubleBufferMode) 147 attachments[i++] = __DRI_BUFFER_BACK_LEFT; 148 if (fb->Visual.haveDepthBuffer && fb->Visual.haveStencilBuffer) 149 attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; 150 else if (fb->Visual.haveDepthBuffer) 151 attachments[i++] = __DRI_BUFFER_DEPTH; 152 else if (fb->Visual.haveStencilBuffer) 153 attachments[i++] = __DRI_BUFFER_STENCIL; 154 155 buffers = (*screen->dri2.loader->getBuffers)(drawable, 156 &drawable->w, &drawable->h, 157 attachments, i, &count, 158 drawable->loaderPrivate); 159 if (buffers == NULL) 160 return; 161 162 for (i = 0; i < count; i++) { 163 struct gl_renderbuffer *rb; 164 struct nouveau_surface *s; 165 uint32_t old_handle; 166 int index; 167 168 switch (buffers[i].attachment) { 169 case __DRI_BUFFER_FRONT_LEFT: 170 case __DRI_BUFFER_FAKE_FRONT_LEFT: 171 index = BUFFER_FRONT_LEFT; 172 break; 173 case __DRI_BUFFER_BACK_LEFT: 174 index = BUFFER_BACK_LEFT; 175 break; 176 case __DRI_BUFFER_DEPTH: 177 case __DRI_BUFFER_DEPTH_STENCIL: 178 index = BUFFER_DEPTH; 179 break; 180 case __DRI_BUFFER_STENCIL: 181 index = BUFFER_STENCIL; 182 break; 183 default: 184 assert(0); 185 } 186 187 rb = fb->Attachment[index].Renderbuffer; 188 s = &to_nouveau_renderbuffer(rb)->surface; 189 190 s->width = drawable->w; 191 s->height = drawable->h; 192 s->pitch = buffers[i].pitch; 193 s->cpp = buffers[i].cpp; 194 195 /* Don't bother to reopen the bo if it happens to be 196 * the same. */ 197 if (s->bo) { 198 ret = nouveau_bo_handle_get(s->bo, &old_handle); 199 assert(!ret); 200 } 201 202 if (!s->bo || old_handle != buffers[i].name) { 203 nouveau_bo_ref(NULL, &s->bo); 204 ret = nouveau_bo_handle_ref(context_dev(ctx), 205 buffers[i].name, &s->bo); 206 assert(!ret); 207 208 context_dirty(ctx, FRAMEBUFFER); 209 } 210 } 211 212 _mesa_resize_framebuffer(ctx, fb, drawable->w, drawable->h); 213} 214 215GLboolean 216nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw, 217 __DRIdrawable *dri_read) 218{ 219 if (dri_ctx) { 220 struct nouveau_context *nctx = dri_ctx->driverPrivate; 221 GLcontext *ctx = &nctx->base; 222 223 if (nctx->screen->context == nctx) 224 return GL_TRUE; 225 226 nctx->screen->context = nctx; 227 BITSET_ONES(nctx->dirty); 228 229 /* Ask the X server for new renderbuffers. */ 230 nouveau_update_renderbuffers(dri_ctx, dri_draw, 231 &nctx->drawable.d_stamp); 232 if (dri_draw != dri_read) 233 nouveau_update_renderbuffers(dri_ctx, dri_read, 234 &nctx->drawable.r_stamp); 235 236 /* Pass it down to mesa. */ 237 _mesa_make_current(ctx, dri_draw->driverPrivate, 238 dri_read->driverPrivate); 239 _mesa_update_state(ctx); 240 241 FIRE_RING(context_chan(ctx)); 242 243 } else { 244 _mesa_make_current(NULL, NULL, NULL); 245 } 246 247 return GL_TRUE; 248} 249 250GLboolean 251nouveau_context_unbind(__DRIcontext *dri_ctx) 252{ 253 return GL_TRUE; 254} 255 256void 257nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode) 258{ 259 struct nouveau_context *nctx = to_nouveau_context(ctx); 260 261 nctx->fallback = MAX2(HWTNL, mode); 262 263 if (mode < SWRAST) 264 nouveau_state_emit(ctx); 265 else 266 FIRE_RING(context_chan(ctx)); 267} 268 269void 270nouveau_validate_framebuffer(GLcontext *ctx) 271{ 272 struct nouveau_context *nctx = to_nouveau_context(ctx); 273 __DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context; 274 __DRIdrawable *dri_draw = dri_ctx->driDrawablePriv; 275 __DRIdrawable *dri_read = dri_ctx->driReadablePriv; 276 277 if ((ctx->DrawBuffer->Name == 0 && 278 nctx->drawable.d_stamp != *dri_draw->pStamp) || 279 (dri_draw != dri_read && 280 ctx->ReadBuffer->Name == 0 && 281 nctx->drawable.r_stamp != *dri_read->pStamp)) { 282 if (nctx->drawable.dirty) 283 ctx->Driver.Flush(ctx); 284 285 /* Ask the X server for new renderbuffers. */ 286 nouveau_update_renderbuffers(dri_ctx, dri_draw, 287 &nctx->drawable.d_stamp); 288 if (dri_draw != dri_read) 289 nouveau_update_renderbuffers(dri_ctx, dri_read, 290 &nctx->drawable.r_stamp); 291 292 if (nouveau_next_dirty_state(ctx) >= 0) 293 FIRE_RING(context_chan(ctx)); 294 } 295 296 /* Someone's planning to draw something really soon. */ 297 nctx->drawable.dirty = GL_TRUE; 298} 299