Merge branch '7.8'
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_driver.c
index 1135817fe9a9da450f4659b91ccc820e5e37b66c..4ec864c181c23165b10d44da033d278e6362218c 100644 (file)
-/**************************************************************************
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
 
-Copyright 2006 Stephane Marchesin
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#include "nouveau_context.h"
-//#include "nouveau_state.h"
-#include "nouveau_lock.h"
-#include "nouveau_fifo.h"
 #include "nouveau_driver.h"
-#include "swrast/swrast.h"
-
-#include "context.h"
-#include "framebuffer.h"
-
-#include "utils.h"
-#include "colormac.h"
-
-/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
-GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa,
-                            unsigned int      param,
-                            uint64_t*         value)
-{
-       struct drm_nouveau_getparam getp;
-
-       getp.param = param;
-       if (!value || drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_GETPARAM,
-                                         &getp, sizeof(getp)))
-               return GL_FALSE;
-       *value = getp.value;
-       return GL_TRUE;
-}
-
-/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */
-GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa,
-                            unsigned int      param,
-                            uint64_t          value)
-{
-       struct drm_nouveau_setparam setp;
-
-       setp.param = param;
-       setp.value = value;
-       if (drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_SETPARAM, &setp,
-                               sizeof(setp)))
-               return GL_FALSE;
-       return GL_TRUE;
-}
-
-/* Return the width and height of the current color buffer */
-static void nouveauGetBufferSize( GLframebuffer *buffer,
-               GLuint *width, GLuint *height )
-{
-       GET_CURRENT_CONTEXT(ctx);
-       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+#include "nouveau_context.h"
+#include "nouveau_fbo.h"
+#include "nouveau_util.h"
 
-       LOCK_HARDWARE( nmesa );
-       *width  = nmesa->driDrawable->w;
-       *height = nmesa->driDrawable->h;
-       UNLOCK_HARDWARE( nmesa );
-}
+#include "drivers/common/meta.h"
 
-/* glGetString */
-static const GLubyte *nouveauGetString( GLcontext *ctx, GLenum name )
+static const GLubyte *
+nouveau_get_string(GLcontext *ctx, GLenum name)
 {
-       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
        static char buffer[128];
-       const char * card_name = "Unknown";
-       GLuint agp_mode = 0;
+       char hardware_name[32];
 
-       switch ( name ) {
+       switch (name) {
                case GL_VENDOR:
-                       return (GLubyte *)DRIVER_AUTHOR;
+                       return (GLubyte *)"Nouveau";
 
                case GL_RENDERER:
-                       card_name=nmesa->screen->card->name;
-
-                       switch(nmesa->screen->bus_type)
-                       {
-                               case NV_PCI:
-                               case NV_PCIE:
-                               default:
-                                       agp_mode=0;
-                                       break;
-                               case NV_AGP:
-                                       agp_mode=nmesa->screen->agp_mode;
-                                       break;
-                       }
-                       driGetRendererString( buffer, card_name, DRIVER_DATE,
-                                       agp_mode );
+                       sprintf(hardware_name, "nv%02X", context_chipset(ctx));
+                       driGetRendererString(buffer, hardware_name, DRIVER_DATE, 0);
+
                        return (GLubyte *)buffer;
                default:
                        return NULL;
        }
 }
 
-/* glFlush */
-static void nouveauFlush( GLcontext *ctx )
+static void
+nouveau_flush(GLcontext *ctx)
 {
-       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+       struct nouveau_context *nctx = to_nouveau_context(ctx);
+       struct nouveau_channel *chan = context_chan(ctx);
+
+       FIRE_RING(chan);
+
+       if (ctx->DrawBuffer->Name == 0 &&
+           ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+               __DRIscreen *screen = nctx->screen->dri_screen;
+               __DRIdri2LoaderExtension *dri2 = screen->dri2.loader;
+               __DRIdrawable *drawable = nctx->dri_context->driDrawablePriv;
 
-       if (ctx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT)
-               nouveauDoSwapBuffers(nmesa, nmesa->driDrawable);
-       FIRE_RING();
+               dri2->flushFrontBuffer(drawable, drawable->loaderPrivate);
+       }
 }
 
-/* glFinish */
-static void nouveauFinish( GLcontext *ctx )
+static void
+nouveau_finish(GLcontext *ctx)
 {
-       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
-
-       nouveauFlush( ctx );
-       nouveauWaitForIdle( nmesa );
+       nouveau_flush(ctx);
 }
 
-/* glClear */
-static void nouveauClear( GLcontext *ctx, GLbitfield mask )
+void
+nouveau_clear(GLcontext *ctx, GLbitfield buffers)
 {
-       uint32_t clear_value;
-       nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
-
-       /* FIXME: should we clear front buffer, even if asked to do it? */
-       if (mask & (BUFFER_BIT_FRONT_LEFT|BUFFER_BIT_BACK_LEFT)) {
-               GLubyte c[4];
-               int color_bits = 32;
-               int color_mask = 0xffffffff;
-
-               UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,ctx->Color.ClearColor);
-               clear_value = PACK_COLOR_8888(c[3],c[0],c[1],c[2]);
-
-               if (ctx->DrawBuffer) {
-                       /* FIXME: find correct color buffer, instead of [0] */
-                       if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
-                               color_bits = ctx->DrawBuffer->_ColorDrawBuffers[0]->RedBits;
-                               color_bits += ctx->DrawBuffer->_ColorDrawBuffers[0]->GreenBits;
-                               color_bits += ctx->DrawBuffer->_ColorDrawBuffers[0]->BlueBits;
-                               color_bits += ctx->DrawBuffer->_ColorDrawBuffers[0]->AlphaBits;
-                       }
-               }
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       int x, y, w, h;
+       int i, buf;
 
-               if (color_bits<24) {
-                       clear_value = PACK_COLOR_565(c[0],c[1],c[2]);
-                       color_mask = 0xffff;
-               }
+       nouveau_validate_framebuffer(ctx);
+       get_scissors(fb, &x, &y, &w, &h);
 
-               nouveauClearBuffer(ctx, nmesa->color_buffer,
-                       clear_value, color_mask);
-       }
+       for (i = 0; i < BUFFER_COUNT; i++) {
+               struct nouveau_surface *s;
+               unsigned mask, value;
 
-       if (mask & (BUFFER_BIT_DEPTH)) {
-               int depth_bits = 24;
-               int depth_mask;
-               if (ctx->DrawBuffer) {
-                       if (ctx->DrawBuffer->_DepthBuffer) {
-                               depth_bits = ctx->DrawBuffer->_DepthBuffer->DepthBits;
-                       }
-               }
+               buf = buffers & (1 << i);
+               if (!buf)
+                       continue;
 
-               switch(depth_bits) {
-                       case 16:
-                               clear_value = (uint32_t) (ctx->Depth.Clear * 32767.0);
-                               depth_mask = 0xffff;
-                               break;
-                       default:
-                               clear_value = ((uint32_t) (ctx->Depth.Clear * 16777215.0)) << 8;
-                               depth_mask = 0xffffff00;
-                               break;
-               }
+               s = &to_nouveau_renderbuffer(
+                       fb->Attachment[i].Renderbuffer->Wrapped)->surface;
 
-               nouveauClearBuffer(ctx, nmesa->depth_buffer,
-                       clear_value, depth_mask);
-       }
+               if (buf & BUFFER_BITS_COLOR) {
+                       mask = pack_rgba_i(s->format, ctx->Color.ColorMask[0]);
+                       value = pack_rgba_f(s->format, ctx->Color.ClearColor);
 
-       if (mask & (BUFFER_BIT_STENCIL)) {
-               int stencil_bits = 0;
-               if (ctx->DrawBuffer) {
-                       if (ctx->DrawBuffer->_StencilBuffer) {
-                               stencil_bits = ctx->DrawBuffer->_StencilBuffer->StencilBits;
-                       }
-               }
+                       if (mask)
+                               context_drv(ctx)->surface_fill(
+                                       ctx, s, mask, value, x, y, w, h);
+
+                       buffers &= ~buf;
+
+               } else if (buf & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
+                       mask = pack_zs_i(s->format,
+                                        (buffers & BUFFER_BIT_DEPTH &&
+                                         ctx->Depth.Mask) ? ~0 : 0,
+                                        (buffers & BUFFER_BIT_STENCIL ?
+                                         ctx->Stencil.WriteMask[0] : 0));
+                       value = pack_zs_f(s->format,
+                                         ctx->Depth.Clear,
+                                         ctx->Stencil.Clear);
 
-               if (stencil_bits>0) {
-                       nouveauClearBuffer(ctx, nmesa->depth_buffer,
-                               ctx->Stencil.Clear, (1<<stencil_bits)-1);
-               }       
+                       if (mask)
+                               context_drv(ctx)->surface_fill(
+                                       ctx, s, mask, value, x, y, w, h);
+
+                       buffers &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
+               }
        }
+
+       if (buffers)
+               _mesa_meta_Clear(ctx, buffers);
 }
 
-void nouveauDriverInitFunctions( struct dd_function_table *functions )
+void
+nouveau_driver_functions_init(struct dd_function_table *functions)
 {
-       functions->GetBufferSize        = nouveauGetBufferSize;
-       functions->ResizeBuffers        = _mesa_resize_framebuffer;
-       functions->GetString            = nouveauGetString;
-       functions->Flush                = nouveauFlush;
-       functions->Finish               = nouveauFinish;
-       functions->Clear                = nouveauClear;
+       functions->GetString = nouveau_get_string;
+       functions->Flush = nouveau_flush;
+       functions->Finish = nouveau_finish;
+       functions->Clear = nouveau_clear;
+       functions->DrawPixels = _mesa_meta_DrawPixels;
+       functions->CopyPixels = _mesa_meta_CopyPixels;
+       functions->Bitmap = _mesa_meta_Bitmap;
+       functions->BlitFramebuffer = _mesa_meta_BlitFramebuffer;
 }
-