Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / mesa / drivers / dri / intel / intel_context.c
index e714e2e90b070fc75e1fc0c1f0bee83edfd54f5f..152cdcaf37d69b73fbc166a27413697c0e5cf0b5 100644 (file)
@@ -29,6 +29,7 @@
 #include "main/glheader.h"
 #include "main/context.h"
 #include "main/extensions.h"
+#include "main/fbobject.h"
 #include "main/framebuffer.h"
 #include "main/imports.h"
 #include "main/points.h"
@@ -39,8 +40,6 @@
 #include "drivers/common/driverfuncs.h"
 #include "drivers/common/meta.h"
 
-#include "i830_dri.h"
-
 #include "intel_chipset.h"
 #include "intel_buffers.h"
 #include "intel_tex.h"
@@ -68,7 +67,7 @@ int INTEL_DEBUG = (0);
 
 
 static const GLubyte *
-intelGetString(GLcontext * ctx, GLenum name)
+intelGetString(struct gl_context * ctx, GLenum name)
 {
    const struct intel_context *const intel = intel_context(ctx);
    const char *chipset;
@@ -156,6 +155,7 @@ intelGetString(GLcontext * ctx, GLenum name)
          chipset = "Intel(R) G41";
          break;
       case PCI_CHIP_B43_G:
+      case PCI_CHIP_B43_G1:
          chipset = "Intel(R) B43";
          break;
       case PCI_CHIP_ILD_G:
@@ -164,6 +164,19 @@ intelGetString(GLcontext * ctx, GLenum name)
       case PCI_CHIP_ILM_G:
          chipset = "Intel(R) Ironlake Mobile";
          break;
+      case PCI_CHIP_SANDYBRIDGE_GT1:
+      case PCI_CHIP_SANDYBRIDGE_GT2:
+      case PCI_CHIP_SANDYBRIDGE_GT2_PLUS:
+        chipset = "Intel(R) Sandybridge Desktop";
+        break;
+      case PCI_CHIP_SANDYBRIDGE_M_GT1:
+      case PCI_CHIP_SANDYBRIDGE_M_GT2:
+      case PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS:
+        chipset = "Intel(R) Sandybridge Mobile";
+        break;
+      case PCI_CHIP_SANDYBRIDGE_S:
+        chipset = "Intel(R) Sandybridge Server";
+        break;
       default:
          chipset = "Unknown Intel Chipset";
          break;
@@ -178,7 +191,7 @@ intelGetString(GLcontext * ctx, GLenum name)
 }
 
 static void
-intel_flush_front(GLcontext *ctx)
+intel_flush_front(struct gl_context *ctx)
 {
    struct intel_context *intel = intel_context(ctx);
     __DRIcontext *driContext = intel->driContext;
@@ -237,7 +250,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
     * thus ignore the invalidate. */
    drawable->lastStamp = drawable->dri2.stamp;
 
-   if (INTEL_DEBUG & DEBUG_DRI)
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
    screen = intel->intelScreen->driScrnPriv;
@@ -355,7 +368,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
        case __DRI_BUFFER_ACCUM:
        default:
           fprintf(stderr,
-                  "unhandled buffer attach event, attacment type %d\n",
+                  "unhandled buffer attach event, attachment type %d\n",
                   buffers[i].attachment);
           return;
        }
@@ -366,19 +379,20 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
        if (rb->region && rb->region->name == buffers[i].name)
             continue;
 
-       if (INTEL_DEBUG & DEBUG_DRI)
+       if (unlikely(INTEL_DEBUG & DEBUG_DRI))
          fprintf(stderr,
                  "attaching buffer %d, at %d, cpp %d, pitch %d\n",
                  buffers[i].name, buffers[i].attachment,
                  buffers[i].cpp, buffers[i].pitch);
        
        if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_region) {
-         if (INTEL_DEBUG & DEBUG_DRI)
+         if (unlikely(INTEL_DEBUG & DEBUG_DRI))
             fprintf(stderr, "(reusing depth buffer as stencil)\n");
          intel_region_reference(&region, depth_region);
        }
        else
-          region = intel_region_alloc_for_handle(intel, buffers[i].cpp,
+          region = intel_region_alloc_for_handle(intel->intelScreen,
+                                                buffers[i].cpp,
                                                 drawable->w,
                                                 drawable->h,
                                                 buffers[i].pitch / buffers[i].cpp,
@@ -420,7 +434,7 @@ intel_prepare_render(struct intel_context *intel)
    __DRIdrawable *drawable;
 
    drawable = driContext->driDrawablePriv;
-   if (drawable->dri2.stamp != driContext->dri2.draw_stamp) {
+   if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) {
       if (drawable->lastStamp != drawable->dri2.stamp)
         intel_update_renderbuffers(driContext, drawable);
       intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
@@ -428,7 +442,7 @@ intel_prepare_render(struct intel_context *intel)
    }
 
    drawable = driContext->driReadablePriv;
-   if (drawable->dri2.stamp != driContext->dri2.read_stamp) {
+   if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) {
       if (drawable->lastStamp != drawable->dri2.stamp)
         intel_update_renderbuffers(driContext, drawable);
       driContext->dri2.read_stamp = drawable->dri2.stamp;
@@ -440,10 +454,32 @@ intel_prepare_render(struct intel_context *intel)
     */
    if (intel->is_front_buffer_rendering)
       intel->front_buffer_dirty = GL_TRUE;
+
+   /* Wait for the swapbuffers before the one we just emitted, so we
+    * don't get too many swaps outstanding for apps that are GPU-heavy
+    * but not CPU-heavy.
+    *
+    * We're using intelDRI2Flush (called from the loader before
+    * swapbuffer) and glFlush (for front buffer rendering) as the
+    * indicator that a frame is done and then throttle when we get
+    * here as we prepare to render the next frame.  At this point for
+    * round trips for swap/copy and getting new buffers are done and
+    * we'll spend less time waiting on the GPU.
+    *
+    * Unfortunately, we don't have a handle to the batch containing
+    * the swap, and getting our hands on that doesn't seem worth it,
+    * so we just us the first batch we emitted after the last swap.
+    */
+   if (intel->need_throttle && intel->first_post_swapbuffers_batch) {
+      drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
+      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
+      intel->first_post_swapbuffers_batch = NULL;
+      intel->need_throttle = GL_FALSE;
+   }
 }
 
 static void
-intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 {
     struct intel_context *intel = intel_context(ctx);
     __DRIcontext *driContext = intel->driContext;
@@ -451,8 +487,7 @@ intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
     if (intel->saved_viewport)
        intel->saved_viewport(ctx, x, y, w, h);
 
-    if (!intel->using_dri2_swapbuffers &&
-       !intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+    if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
        dri2InvalidateDrawable(driContext->driDrawablePriv);
        dri2InvalidateDrawable(driContext->driReadablePriv);
     }
@@ -476,7 +511,7 @@ static const struct dri_debug_control debug_control[] = {
    { "prim",  DEBUG_PRIMS },
    { "vert",  DEBUG_VERTS },
    { "dri",   DEBUG_DRI },
-   { "dma",   DEBUG_DMA },
+   { "sf",    DEBUG_SF },
    { "san",   DEBUG_SANITY },
    { "sleep", DEBUG_SLEEP },
    { "stats", DEBUG_STATS },
@@ -493,7 +528,7 @@ static const struct dri_debug_control debug_control[] = {
 
 
 static void
-intelInvalidateState(GLcontext * ctx, GLuint new_state)
+intelInvalidateState(struct gl_context * ctx, GLuint new_state)
 {
     struct intel_context *intel = intel_context(ctx);
 
@@ -510,7 +545,7 @@ intelInvalidateState(GLcontext * ctx, GLuint new_state)
 }
 
 void
-intel_flush(GLcontext *ctx)
+intel_flush(struct gl_context *ctx)
 {
    struct intel_context *intel = intel_context(ctx);
 
@@ -525,36 +560,17 @@ intel_flush(GLcontext *ctx)
 }
 
 static void
-intel_glFlush(GLcontext *ctx)
+intel_glFlush(struct gl_context *ctx)
 {
    struct intel_context *intel = intel_context(ctx);
 
    intel_flush(ctx);
-
    intel_flush_front(ctx);
-
-   /* We're using glFlush as an indicator that a frame is done, which is
-    * what DRI2 does before calling SwapBuffers (and means we should catch
-    * people doing front-buffer rendering, as well)..
-    *
-    * Wait for the swapbuffers before the one we just emitted, so we don't
-    * get too many swaps outstanding for apps that are GPU-heavy but not
-    * CPU-heavy.
-    *
-    * Unfortunately, we don't have a handle to the batch containing the swap,
-    * and getting our hands on that doesn't seem worth it, so we just us the
-    * first batch we emitted after the last swap.
-    */
-   if (!intel->using_dri2_swapbuffers &&
-       intel->first_post_swapbuffers_batch != NULL) {
-      drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
-      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
-      intel->first_post_swapbuffers_batch = NULL;
-   }
+   intel->need_throttle = GL_TRUE;
 }
 
 void
-intelFinish(GLcontext * ctx)
+intelFinish(struct gl_context * ctx)
 {
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    int i;
@@ -568,7 +584,7 @@ intelFinish(GLcontext * ctx)
        irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
 
        if (irb && irb->region)
-         dri_bo_wait_rendering(irb->region->buffer);
+         drm_intel_bo_wait_rendering(irb->region->buffer);
    }
    if (fb->_DepthBuffer) {
       /* XXX: Wait on buffer idle */
@@ -601,16 +617,17 @@ intelInitDriverFunctions(struct dd_function_table *functions)
 GLboolean
 intelInitContext(struct intel_context *intel,
                 int api,
-                 const __GLcontextModes * mesaVis,
+                 const struct gl_config * mesaVis,
                  __DRIcontext * driContextPriv,
                  void *sharedContextPrivate,
                  struct dd_function_table *functions)
 {
-   GLcontext *ctx = &intel->ctx;
-   GLcontext *shareCtx = (GLcontext *) sharedContextPrivate;
+   struct gl_context *ctx = &intel->ctx;
+   struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate;
    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
    struct intel_screen *intelScreen = sPriv->private;
    int bo_reuse_mode;
+   struct gl_config visual;
 
    /* we can't do anything without a connection to the device */
    if (intelScreen->bufmgr == NULL)
@@ -622,6 +639,11 @@ intelInitContext(struct intel_context *intel,
       functions->Viewport = intel_viewport;
    }
 
+   if (mesaVis == NULL) {
+      memset(&visual, 0, sizeof visual);
+      mesaVis = &visual;
+   }
+
    if (!_mesa_initialize_context_for_api(&intel->ctx, api, mesaVis, shareCtx,
                                         functions, (void *) intel)) {
       printf("%s: failed to init mesa context\n", __FUNCTION__);
@@ -633,6 +655,7 @@ intelInitContext(struct intel_context *intel,
    intel->driContext = driContextPriv;
    intel->driFd = sPriv->fd;
 
+   intel->has_xrgb_textures = GL_TRUE;
    if (IS_GEN6(intel->intelScreen->deviceID)) {
       intel->gen = 6;
       intel->needs_ff_sync = GL_TRUE;
@@ -654,6 +677,10 @@ intelInitContext(struct intel_context *intel,
       }
    } else {
       intel->gen = 2;
+      if (intel->intelScreen->deviceID == PCI_CHIP_I830_M ||
+         intel->intelScreen->deviceID == PCI_CHIP_845_G) {
+        intel->has_xrgb_textures = GL_FALSE;
+      }
    }
 
    driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
@@ -708,13 +735,14 @@ intelInitContext(struct intel_context *intel,
    ctx->Const.MaxPointSizeAA = 3.0;
    ctx->Const.PointSizeGranularity = 1.0;
 
+   ctx->Const.MaxSamples = 1.0;
+
    /* reinitialize the context point state.
-    * It depend on constants in __GLcontextRec::Const
+    * It depend on constants in __struct gl_contextRec::Const
     */
    _mesa_init_point(ctx);
 
    meta_init_metaops(ctx, &intel->meta);
-   ctx->Const.MaxColorAttachments = 4;  /* XXX FBO: review this */
    if (intel->gen >= 4) {
       if (MAX_WIDTH > 8192)
         ctx->Const.MaxRenderbufferSize = 8192;
@@ -772,6 +800,11 @@ intelInitContext(struct intel_context *intel,
    if (INTEL_DEBUG & DEBUG_BUFMGR)
       dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE);
 
+   /* XXX force SIMD8 kernel for Sandybridge before we fixed
+      SIMD16 interpolation. */
+   if (intel->gen == 6)
+       INTEL_DEBUG |= DEBUG_GLSL_FORCE;
+
    intel->batch = intel_batchbuffer_alloc(intel);
 
    intel_fbo_init(intel);
@@ -821,8 +854,6 @@ intelDestroyContext(__DRIcontext * driContextPriv)
 
    assert(intel);               /* should never be null */
    if (intel) {
-      GLboolean release_texture_heaps;
-
       INTEL_FIREVERTICES(intel);
 
       _mesa_meta_free(&intel->ctx);
@@ -831,7 +862,6 @@ intelDestroyContext(__DRIcontext * driContextPriv)
 
       intel->vtbl.destroy(intel);
 
-      release_texture_heaps = (intel->ctx.Shared->RefCount == 1);
       _swsetup_DestroyContext(&intel->ctx);
       _tnl_DestroyContext(&intel->ctx);
       _vbo_DestroyContext(&intel->ctx);
@@ -844,23 +874,11 @@ intelDestroyContext(__DRIcontext * driContextPriv)
 
       free(intel->prim.vb);
       intel->prim.vb = NULL;
-      dri_bo_unreference(intel->prim.vb_bo);
+      drm_intel_bo_unreference(intel->prim.vb_bo);
       intel->prim.vb_bo = NULL;
-      dri_bo_unreference(intel->first_post_swapbuffers_batch);
+      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
       intel->first_post_swapbuffers_batch = NULL;
 
-      if (release_texture_heaps) {
-         /* Nothing is currently done here to free texture heaps;
-          * but we're not using the texture heap utilities, so I
-          * rather think we shouldn't.  I've taken a look, and can't
-          * find any private texture data hanging around anywhere, but
-          * I'm not yet certain there isn't any at all...
-          */
-         /* if (INTEL_DEBUG & DEBUG_TEXTURE)
-            fprintf(stderr, "do something to free texture heaps\n");
-          */
-      }
-
       driDestroyOptionCache(&intel->optionCache);
 
       /* free the Mesa context */
@@ -874,6 +892,9 @@ intelDestroyContext(__DRIcontext * driContextPriv)
 GLboolean
 intelUnbindContext(__DRIcontext * driContextPriv)
 {
+   /* Unset current context and dispath table */
+   _mesa_make_current(NULL, NULL, NULL);
+
    return GL_TRUE;
 }
 
@@ -899,14 +920,21 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
    }
 
    if (driContextPriv) {
-      struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
-      struct gl_framebuffer *readFb = driReadPriv->driverPrivate;
+      struct gl_framebuffer *fb, *readFb;
+      
+      if (driDrawPriv == NULL && driReadPriv == NULL) {
+        fb = _mesa_get_incomplete_framebuffer();
+        readFb = _mesa_get_incomplete_framebuffer();
+      } else {
+        fb = driDrawPriv->driverPrivate;
+        readFb = driReadPriv->driverPrivate;
+        driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
+        driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
+      }
 
-      driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
-      driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
       intel_prepare_render(intel);
       _mesa_make_current(&intel->ctx, fb, readFb);
-
+      
       /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer
        * is NULL at that point.  We can't call _mesa_makecurrent()
        * first, since we need the buffer size for the initial