Refactor and fix core vblank support
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_context.c
index 683e6d6ea63f95c134e0b6dc94761cf0a4ae5d87..5ef24d827064a000f044c82dd75e329df48f3177 100644 (file)
@@ -31,19 +31,26 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "matrix.h"
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
-#include "array_cache/acache.h"
+#include "framebuffer.h"
 
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
+#include "tnl/t_vp_build.h"
 
 #include "drivers/common/driverfuncs.h"
 
 #include "nouveau_context.h"
-#include "nouveau_ioctl.h"
 #include "nouveau_driver.h"
 //#include "nouveau_state.h"
 #include "nouveau_span.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
 #include "nouveau_tex.h"
+#include "nouveau_msg.h"
+#include "nouveau_reg.h"
+#include "nouveau_lock.h"
+#include "nouveau_query.h"
+#include "nv04_swtcl.h"
 #include "nv10_swtcl.h"
 
 #include "vblank.h"
@@ -55,9 +62,50 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 int NOUVEAU_DEBUG = 0;
 #endif
 
-#define NOUVEAU_FALLBACK_DISABLE 1
-
 static const struct dri_debug_control debug_control[] =
+{
+       { "shaders"   , DEBUG_SHADERS    },
+       { "mem"       , DEBUG_MEM        },
+       { "bufferobj" , DEBUG_BUFFEROBJ  },
+       { NULL        , 0                }
+};
+
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_occlusion_query
+#include "extension_helper.h"
+
+const struct dri_extension common_extensions[] =
+{
+       { NULL,    0 }
+};
+
+const struct dri_extension nv10_extensions[] =
+{
+       { NULL,    0 }
+};
+
+const struct dri_extension nv20_extensions[] =
+{
+       { NULL,    0 }
+};
+
+const struct dri_extension nv30_extensions[] =
+{
+       { "GL_ARB_fragment_program",    NULL                            },
+       { NULL,    0 }
+};
+
+const struct dri_extension nv40_extensions[] =
+{
+   /* ARB_vp can be moved to nv20/30 once the shader backend has been
+    * written for those cards.
+    */
+       { "GL_ARB_vertex_program",      GL_ARB_vertex_program_functions },
+       { "GL_ARB_occlusion_query",     GL_ARB_occlusion_query_functions},
+       { NULL, 0 }
+};
+
+const struct dri_extension nv50_extensions[] =
 {
        { NULL,    0 }
 };
@@ -73,19 +121,45 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
        struct dd_function_table functions;
        nouveauContextPtr nmesa;
        nouveauScreenPtr screen;
-       int i;
 
        /* Allocate the context */
        nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) );
        if ( !nmesa )
                return GL_FALSE;
 
-       /* Init default driver functions then plug in our Radeon-specific functions
+       nmesa->driContext = driContextPriv;
+       nmesa->driScreen = sPriv;
+       nmesa->driDrawable = NULL;
+       nmesa->hHWContext = driContextPriv->hHWContext;
+       nmesa->driHwLock = &sPriv->pSAREA->lock;
+       nmesa->driFd = sPriv->fd;
+
+       nmesa->screen = (nouveauScreenPtr)(sPriv->private);
+       screen=nmesa->screen;
+
+       /* Create the hardware context */
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL,
+                               &nmesa->vram_phys))
+          return GL_FALSE;
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_SIZE,
+                               &nmesa->vram_size))
+          return GL_FALSE;
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
+                               &nmesa->gart_phys))
+          return GL_FALSE;
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_SIZE,
+                               &nmesa->gart_size))
+          return GL_FALSE;
+       if (!nouveauFifoInit(nmesa))
+          return GL_FALSE;
+       nouveauObjectInit(nmesa);
+
+
+       /* Init default driver functions then plug in our nouveau-specific functions
         * (the texture functions are especially important)
         */
        _mesa_init_driver_functions( &functions );
        nouveauDriverInitFunctions( &functions );
-       nouveauIoctlInitFunctions( &functions );
        nouveauTexInitFunctions( &functions );
 
        /* Allocate the Mesa context */
@@ -102,51 +176,69 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
        driContextPriv->driverPrivate = nmesa;
        ctx = nmesa->glCtx;
 
-       nmesa->driContext = driContextPriv;
-       nmesa->driScreen = sPriv;
-       nmesa->driDrawable = NULL;
-       nmesa->hHWContext = driContextPriv->hHWContext;
-       nmesa->driHwLock = &sPriv->pSAREA->lock;
-       nmesa->driFd = sPriv->fd;
-
-       nmesa->screen = (nouveauScreenPtr)(sPriv->private);
-       screen=nmesa->screen;
-
        /* Parse configuration files */
        driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
                        screen->driScreen->myNum, "nouveau");
 
-       nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
+       nmesa->sarea = (struct drm_nouveau_sarea *)((char *)sPriv->pSAREA +
                        screen->sarea_priv_offset);
 
+       /* Enable any supported extensions */
+       driInitExtensions(ctx, common_extensions, GL_TRUE);
+       if (nmesa->screen->card->type >= NV_10)
+               driInitExtensions(ctx, nv10_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_20)
+               driInitExtensions(ctx, nv20_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_30)
+               driInitExtensions(ctx, nv30_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_40)
+               driInitExtensions(ctx, nv40_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_50)
+               driInitExtensions(ctx, nv50_extensions, GL_FALSE);
 
        nmesa->current_primitive = -1;
 
+       nouveauShaderInitFuncs(ctx);
+       /* Install Mesa's fixed-function texenv shader support */
+       if (nmesa->screen->card->type >= NV_40)
+               ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
        /* Initialize the swrast */
        _swrast_CreateContext( ctx );
-       _ac_CreateContext( ctx );
+       _vbo_CreateContext( ctx );
        _tnl_CreateContext( ctx );
        _swsetup_CreateContext( ctx );
 
-       switch(nmesa->screen->card_type)
+       _math_matrix_ctr(&nmesa->viewport);
+
+       nouveauDDInitStateFuncs( ctx );
+       nouveauSpanInitFunctions( ctx );
+       nouveauDDInitState( nmesa );
+       switch(nmesa->screen->card->type)
        {
-               case NV_03:
                case NV_04:
                case NV_05:
-               default:
-                       //nv03TriInitFunctions( ctx );
+                       nv04TriInitFunctions( ctx );
                        break;
                case NV_10:
+               case NV_11:
+               case NV_17:
                case NV_20:
                case NV_30:
                case NV_40:
-               case G_70:
+               case NV_44:
+               case NV_50:
+               default:
                        nv10TriInitFunctions( ctx );
                        break;
        }
-       nouveauDDInitStateFuncs( ctx );
-       nouveauSpanInitFunctions( ctx );
-       nouveauDDInitState( nmesa );
+
+       nouveauInitBufferObjects(ctx);
+       if (!nouveauSyncInitFuncs(ctx))
+          return GL_FALSE;
+       nouveauQueryInitFuncs(ctx);
+       nmesa->hw_func.InitCard(nmesa);
+        nouveauInitState(ctx);
 
        driContextPriv->driverPrivate = (void *)nmesa;
 
@@ -185,17 +277,26 @@ GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
                __DRIdrawablePrivate *driReadPriv )
 {
        if ( driContextPriv ) {
-               GET_CURRENT_CONTEXT(ctx);
-               nouveauContextPtr oldNOUVEAUCtx = ctx ? NOUVEAU_CONTEXT(ctx) : NULL;
-               nouveauContextPtr newNOUVEAUCtx = (nouveauContextPtr) driContextPriv->driverPrivate;
-
-               driDrawableInitVBlank( driDrawPriv, newNOUVEAUCtx->vblank_flags );
-               newNOUVEAUCtx->driDrawable = driDrawPriv;
-
-               _mesa_make_current( newNOUVEAUCtx->glCtx,
-                               (GLframebuffer *) driDrawPriv->driverPrivate,
-                               (GLframebuffer *) driReadPriv->driverPrivate );
-
+               nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+               struct gl_framebuffer *draw_fb =
+                       (struct gl_framebuffer*)driDrawPriv->driverPrivate;
+               struct gl_framebuffer *read_fb =
+                       (struct gl_framebuffer*)driReadPriv->driverPrivate;
+
+               driDrawableInitVBlank(driDrawPriv);
+               nmesa->driDrawable = driDrawPriv;
+
+               _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+                                        driDrawPriv->w, driDrawPriv->h);
+               if (draw_fb != read_fb) {
+                       _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+                                                driReadPriv->w,
+                                                driReadPriv->h);
+               }
+               _mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
+
+               nouveau_build_framebuffer(nmesa->glCtx,
+                                         driDrawPriv->driverPrivate);
        } else {
                _mesa_make_current( NULL, NULL, NULL );
        }
@@ -210,3 +311,106 @@ GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
 {
        return GL_TRUE;
 }
+
+void
+nouveauDoSwapBuffers(nouveauContextPtr nmesa, __DRIdrawablePrivate *dPriv)
+{
+       struct gl_framebuffer *fb;
+       nouveauScreenPtr screen = dPriv->driScreenPriv->private;
+       nouveau_renderbuffer_t *src;
+       drm_clip_rect_t *box;
+       int nbox, i;
+
+       fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+       if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
+               src = (nouveau_renderbuffer_t *)
+                       fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+       } else {
+               src = (nouveau_renderbuffer_t *)
+                       fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+       }
+
+       LOCK_HARDWARE(nmesa);
+       nbox = dPriv->numClipRects;
+       box  = dPriv->pClipRects;
+
+       if (nbox) {
+               BEGIN_RING_SIZE(NvSubCtxSurf2D,
+                               NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
+               if (src->mesa._ActualFormat == GL_RGBA8)
+                       OUT_RING       (6); /* X8R8G8B8 */
+               else
+                       OUT_RING       (4); /* R5G6B5 */
+               OUT_RING(((screen->frontPitch * screen->fbFormat) << 16) |
+                         src->pitch);
+               OUT_RING(src->offset);
+               OUT_RING(screen->frontOffset);
+       }
+
+       for (i=0; i<nbox; i++, box++) {
+               BEGIN_RING_SIZE(NvSubImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
+               OUT_RING       (((box->y1 - dPriv->y) << 16) |
+                               (box->x1 - dPriv->x));
+               OUT_RING       ((box->y1 << 16) | box->x1);
+               OUT_RING       (((box->y2 - box->y1) << 16) |
+                               (box->x2 - box->x1));
+       }
+       FIRE_RING();
+
+       UNLOCK_HARDWARE(nmesa);
+}
+
+void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
+{
+       if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+               nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
+
+               if (nmesa->glCtx->Visual.doubleBufferMode) {
+                       _mesa_notifySwapBuffers(nmesa->glCtx);
+                       nouveauDoSwapBuffers(nmesa, dPriv);
+               }
+
+       }
+}
+
+void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
+                         int x, int y, int w, int h)
+{
+}
+
+void nouveauClearBuffer(GLcontext *ctx, nouveau_renderbuffer_t *buffer,
+       int fill, int mask)
+{
+       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       int dimensions;
+
+       if (!buffer) {
+               return;
+       }
+
+       /* FIXME: only support 32 bits atm */
+
+       /* Surface that we will work on */
+       nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
+
+       BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING(0x0b); /* Y32 color format */
+       OUT_RING((buffer->pitch<<16)|buffer->pitch);
+       OUT_RING(buffer->offset);
+       OUT_RING(buffer->offset);
+
+       /* Now clear a rectangle */
+       dimensions = ((buffer->mesa.Height)<<16) | (buffer->mesa.Width);
+
+       nouveauObjectOnSubchannel(nmesa, NvSubGdiRectText, NvGdiRectText);
+
+       BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
+       OUT_RING(3);    /* SRCCOPY */
+
+       BEGIN_RING_SIZE(NvSubGdiRectText, NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_TL, 5);
+       OUT_RING(0);    /* top left */
+       OUT_RING(dimensions);   /* bottom right */
+       OUT_RING(fill);
+       OUT_RING(0);    /* top left */
+       OUT_RING(dimensions);   /* bottom right */
+}