diff options
Diffstat (limited to 'src/mesa/drivers/dri/nouveau/nouveau_context.c')
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_context.c | 157 |
1 files changed, 113 insertions, 44 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index b87b8dbdd0..502e01255c 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Francisco Jerez. + * Copyright (C) 2009-2010 Francisco Jerez. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining @@ -36,26 +36,43 @@ #include "drivers/common/meta.h" #include "drivers/common/driverfuncs.h" #include "swrast/swrast.h" +#include "swrast/s_context.h" #include "vbo/vbo.h" #include "tnl/tnl.h" +#include "tnl/t_context.h" #define need_GL_EXT_framebuffer_object #define need_GL_EXT_fog_coord +#define need_GL_EXT_secondary_color #include "main/remap_helper.h" static const struct dri_extension nouveau_extensions[] = { - { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, { "GL_ARB_multitexture", NULL }, - { "GL_EXT_texture_lod_bias", NULL }, - { "GL_SGIS_generate_mipmap", NULL }, + { "GL_ARB_texture_env_add", NULL }, { "GL_ARB_texture_env_combine", NULL }, { "GL_ARB_texture_env_dot3", NULL }, - { "GL_ARB_texture_env_add", NULL }, + { "GL_ARB_texture_mirrored_repeat", NULL }, { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { "GL_EXT_stencil_wrap", NULL }, + { "GL_EXT_texture_lod_bias", NULL }, + { "GL_NV_blend_square", NULL }, + { "GL_SGIS_generate_mipmap", NULL }, { NULL, NULL } }; +static void +nouveau_channel_flush_notify(struct nouveau_channel *chan) +{ + struct nouveau_context *nctx = chan->user_private; + GLcontext *ctx = &nctx->base; + + if (nctx->fallback < SWRAST && ctx->DrawBuffer) + nouveau_state_emit(&nctx->base); +} + GLboolean nouveau_context_create(const __GLcontextModes *visual, __DRIcontext *dri_ctx, void *share_ctx) @@ -82,18 +99,19 @@ nouveau_context_init(GLcontext *ctx, struct nouveau_screen *screen, { struct nouveau_context *nctx = to_nouveau_context(ctx); struct dd_function_table functions; + int ret; nctx->screen = screen; nctx->fallback = HWTNL; - /* Initialize the function pointers */ + /* Initialize the function pointers. */ _mesa_init_driver_functions(&functions); nouveau_driver_functions_init(&functions); nouveau_bufferobj_functions_init(&functions); nouveau_texture_functions_init(&functions); nouveau_fbo_functions_init(&functions); - /* Initialize the mesa context */ + /* Initialize the mesa context. */ _mesa_initialize_context(ctx, visual, share_ctx, &functions, NULL); nouveau_state_init(ctx); @@ -105,41 +123,70 @@ nouveau_context_init(GLcontext *ctx, struct nouveau_screen *screen, nouveau_span_functions_init(ctx); _mesa_allow_light_in_model(ctx, GL_FALSE); - /* Enable any supported extensions */ + /* Allocate a hardware channel. */ + ret = nouveau_channel_alloc(context_dev(ctx), 0xbeef0201, 0xbeef0202, + &nctx->hw.chan); + if (ret) { + nouveau_error("Error initializing the FIFO.\n"); + return GL_FALSE; + } + + nctx->hw.chan->flush_notify = nouveau_channel_flush_notify; + nctx->hw.chan->user_private = nctx; + + /* Enable any supported extensions. */ driInitExtensions(ctx, nouveau_extensions, GL_TRUE); return GL_TRUE; } void +nouveau_context_deinit(GLcontext *ctx) +{ + struct nouveau_context *nctx = to_nouveau_context(ctx); + + if (TNL_CONTEXT(ctx)) + _tnl_DestroyContext(ctx); + + if (vbo_context(ctx)) + _vbo_DestroyContext(ctx); + + if (SWRAST_CONTEXT(ctx)) + _swrast_DestroyContext(ctx); + + if (ctx->Meta) + _mesa_meta_free(ctx); + + if (nctx->hw.chan) + nouveau_channel_free(&nctx->hw.chan); + + nouveau_bo_state_destroy(ctx); + _mesa_free_context_data(ctx); +} + +void nouveau_context_destroy(__DRIcontext *dri_ctx) { struct nouveau_context *nctx = dri_ctx->driverPrivate; GLcontext *ctx = &nctx->base; - if (nctx->screen->context == nctx) - nctx->screen->context = NULL; - - _tnl_DestroyContext(ctx); - _vbo_DestroyContext(ctx); - _swrast_DestroyContext(ctx); - _mesa_meta_free(ctx); - nouveau_bo_state_destroy(ctx); context_drv(ctx)->context_destroy(ctx); } -static void -nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, - unsigned int *stamp) +void +nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw) { - struct nouveau_context *nctx = context->driverPrivate; - GLcontext *ctx = &nctx->base; - __DRIscreen *screen = context->driScreenPriv; - struct gl_framebuffer *fb = drawable->driverPrivate; + GLcontext *ctx = dri_ctx->driverPrivate; + __DRIscreen *screen = dri_ctx->driScreenPriv; + struct gl_framebuffer *fb = draw->driverPrivate; unsigned int attachments[10]; __DRIbuffer *buffers = NULL; int i = 0, count, ret; + if (draw->lastStamp == *draw->pStamp) + return; + draw->lastStamp = *draw->pStamp; + attachments[i++] = __DRI_BUFFER_FRONT_LEFT; if (fb->Visual.doubleBufferMode) attachments[i++] = __DRI_BUFFER_BACK_LEFT; @@ -150,10 +197,9 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, else if (fb->Visual.haveStencilBuffer) attachments[i++] = __DRI_BUFFER_STENCIL; - buffers = (*screen->dri2.loader->getBuffers)(drawable, - &drawable->w, &drawable->h, + buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h, attachments, i, &count, - drawable->loaderPrivate); + draw->loaderPrivate); if (buffers == NULL) return; @@ -185,8 +231,8 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, rb = fb->Attachment[index].Renderbuffer; s = &to_nouveau_renderbuffer(rb)->surface; - s->width = drawable->w; - s->height = drawable->h; + s->width = draw->w; + s->height = draw->h; s->pitch = buffers[i].pitch; s->cpp = buffers[i].cpp; @@ -202,12 +248,25 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, ret = nouveau_bo_handle_ref(context_dev(ctx), buffers[i].name, &s->bo); assert(!ret); - - context_dirty(ctx, FRAMEBUFFER); } } - _mesa_resize_framebuffer(ctx, fb, drawable->w, drawable->h); + _mesa_resize_framebuffer(NULL, fb, draw->w, draw->h); +} + +static void +update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw, + int *stamp) +{ + GLcontext *ctx = dri_ctx->driverPrivate; + struct gl_framebuffer *fb = draw->driverPrivate; + + *stamp = *draw->pStamp; + + nouveau_update_renderbuffers(dri_ctx, draw); + _mesa_resize_framebuffer(ctx, fb, draw->w, draw->h); + + context_dirty(ctx, FRAMEBUFFER); } GLboolean @@ -218,17 +277,15 @@ nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw, struct nouveau_context *nctx = dri_ctx->driverPrivate; GLcontext *ctx = &nctx->base; - if (nctx->screen->context != nctx) { - nctx->screen->context = nctx; - BITSET_ONES(nctx->dirty); - } - /* Ask the X server for new renderbuffers. */ - nouveau_update_renderbuffers(dri_ctx, dri_draw, - &nctx->drawable.d_stamp); - if (dri_draw != dri_read) - nouveau_update_renderbuffers(dri_ctx, dri_read, - &nctx->drawable.r_stamp); + if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer) + update_framebuffer(dri_ctx, dri_draw, + &dri_ctx->dri2.draw_stamp); + + if (dri_draw != dri_read && + dri_read->driverPrivate != ctx->WinSysReadBuffer) + update_framebuffer(dri_ctx, dri_read, + &dri_ctx->dri2.read_stamp); /* Pass it down to mesa. */ _mesa_make_current(ctx, dri_draw->driverPrivate, @@ -266,8 +323,20 @@ nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode) void nouveau_validate_framebuffer(GLcontext *ctx) { - struct nouveau_context *nctx = to_nouveau_context(ctx); + __DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context; + __DRIdrawable *dri_draw = dri_ctx->driDrawablePriv; + __DRIdrawable *dri_read = dri_ctx->driReadablePriv; - /* Someone's planning to draw something really soon. */ - nctx->drawable.dirty = GL_TRUE; + if (ctx->DrawBuffer->Name == 0 && + dri_ctx->dri2.draw_stamp != *dri_draw->pStamp) + update_framebuffer(dri_ctx, dri_draw, + &dri_ctx->dri2.draw_stamp); + + if (ctx->ReadBuffer->Name == 0 && dri_draw != dri_read && + dri_ctx->dri2.read_stamp != *dri_read->pStamp) + update_framebuffer(dri_ctx, dri_read, + &dri_ctx->dri2.read_stamp); + + if (nouveau_next_dirty_state(ctx) >= 0) + FIRE_RING(context_chan(ctx)); } |