dri/nouveau: Enable NV_fog_distance on NV10 and NV20 hardware
[mesa.git] / src / mesa / drivers / dri / intel / intel_fbo.c
index f48703e155cb43a1dafcc548b403918d43600007..4537f1fb97b1b1ce0a6e6ca4d4ac00ae8b12280e 100644 (file)
@@ -70,24 +70,15 @@ intel_new_framebuffer(struct gl_context * ctx, GLuint name)
 static void
 intel_delete_renderbuffer(struct gl_renderbuffer *rb)
 {
-   GET_CURRENT_CONTEXT(ctx);
-   struct intel_context *intel = intel_context(ctx);
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
 
    ASSERT(irb);
 
-   if (intel && irb->region) {
-      intel_region_release(&irb->region);
-   }
-   if (intel && irb->hiz_region) {
-      intel_region_release(&irb->hiz_region);
-   }
-   if (intel && irb->wrapped_depth) {
-      _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
-   }
-   if (intel && irb->wrapped_stencil) {
-      _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
-   }
+   intel_region_release(&irb->region);
+   intel_region_release(&irb->hiz_region);
+
+   _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
+   _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
 
    free(irb);
 }
@@ -107,17 +98,11 @@ intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
 }
 
 
-static struct gl_renderbuffer*
-intel_create_wrapped_renderbuffer(struct gl_context * ctx,
-                                 struct gl_renderbuffer *wrapper,
-                                 gl_format format);
-
-
 /**
  * Called via glRenderbufferStorageEXT() to set the format and allocate
  * storage for a user-created renderbuffer.
  */
-static GLboolean
+GLboolean
 intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
                                  GLenum internalFormat,
                                  GLuint width, GLuint height)
@@ -188,6 +173,9 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
 
    if (irb->Base.Format == MESA_FORMAT_S8) {
       /*
+       * The stencil buffer is W tiled. However, we request from the kernel a
+       * non-tiled buffer because the GTT is incapable of W fencing.
+       *
        * The stencil buffer has quirky pitch requirements.  From Vol 2a,
        * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
        *    The pitch must be set to 2x the value computed based on width, as
@@ -195,15 +183,14 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
        * To accomplish this, we resort to the nasty hack of doubling the drm
        * region's cpp and halving its height.
        *
-       * If we neglect to double the pitch, then drm_intel_gem_bo_map_gtt()
-       * maps the memory incorrectly.
+       * If we neglect to double the pitch, then render corruption occurs.
        */
       irb->region = intel_region_alloc(intel->intelScreen,
-                                      I915_TILING_Y,
+                                      I915_TILING_NONE,
                                       cpp * 2,
-                                      width,
-                                      height / 2,
-                                      GL_TRUE);
+                                      ALIGN(width, 64),
+                                      ALIGN((height + 1) / 2, 64),
+                                      true);
       if (!irb->region)
        return false;
 
@@ -214,9 +201,9 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
       struct gl_renderbuffer *depth_rb;
       struct gl_renderbuffer *stencil_rb;
 
-      depth_rb = intel_create_wrapped_renderbuffer(ctx, rb,
+      depth_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
                                                   MESA_FORMAT_X8_Z24);
-      stencil_rb = intel_create_wrapped_renderbuffer(ctx, rb,
+      stencil_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
                                                     MESA_FORMAT_S8);
       ok = depth_rb && stencil_rb;
       ok = ok && intel_alloc_renderbuffer_storage(ctx, depth_rb,
@@ -236,12 +223,14 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
         return false;
       }
 
+      depth_rb->Wrapped = rb;
+      stencil_rb->Wrapped = rb;
       _mesa_reference_renderbuffer(&irb->wrapped_depth, depth_rb);
       _mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
 
    } else {
       irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
-                                      width, height, GL_TRUE);
+                                      width, height, true);
       if (!irb->region)
         return false;
 
@@ -251,7 +240,7 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
                                              irb->region->cpp,
                                              irb->region->width,
                                              irb->region->height,
-                                             GL_TRUE);
+                                             true);
         if (!irb->hiz_region) {
            intel_region_release(&irb->region);
            return false;
@@ -259,7 +248,7 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
       }
    }
 
-   return GL_TRUE;
+   return true;
 }
 
 
@@ -280,9 +269,18 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
    if (image == NULL)
       return;
 
+   /* __DRIimage is opaque to the core so it has to be checked here */
+   switch (image->format) {
+   case MESA_FORMAT_RGBA8888_REV:
+      _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
+            "glEGLImageTargetRenderbufferStorage(unsupported image format");
+      return;
+      break;
+   default:
+      break;
+   }
+
    irb = intel_renderbuffer(rb);
-   if (irb->region)
-      intel_region_release(&irb->region);
    intel_region_reference(&irb->region, image->region);
 
    rb->InternalFormat = image->internal_format;
@@ -309,7 +307,7 @@ intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
    rb->Height = height;
    rb->InternalFormat = internalFormat;
 
-   return GL_TRUE;
+   return true;
 }
 
 
@@ -321,7 +319,7 @@ intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
 
    _mesa_resize_framebuffer(ctx, fb, width, height);
 
-   fb->Initialized = GL_TRUE; /* XXX remove someday */
+   fb->Initialized = true; /* XXX remove someday */
 
    if (fb->Name != 0) {
       return;
@@ -346,36 +344,9 @@ intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
                         GLenum internalFormat, GLuint width, GLuint height)
 {
    _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
-   return GL_FALSE;
-}
-
-
-void
-intel_renderbuffer_set_region(struct intel_context *intel,
-                             struct intel_renderbuffer *rb,
-                             struct intel_region *region)
-{
-   struct intel_region *old;
-
-   old = rb->region;
-   rb->region = NULL;
-   intel_region_reference(&rb->region, region);
-   intel_region_release(&old);
+   return false;
 }
 
-
-void
-intel_renderbuffer_set_hiz_region(struct intel_context *intel,
-                                 struct intel_renderbuffer *rb,
-                                 struct intel_region *region)
-{
-   struct intel_region *old = rb->hiz_region;
-   rb->hiz_region = NULL;
-   intel_region_reference(&rb->hiz_region, region);
-   intel_region_release(&old);
-}
-
-
 /**
  * Create a new intel_renderbuffer which corresponds to an on-screen window,
  * not a user-created renderbuffer.
@@ -409,9 +380,9 @@ intel_create_renderbuffer(gl_format format)
 }
 
 
-static struct gl_renderbuffer *
+struct gl_renderbuffer*
 intel_create_wrapped_renderbuffer(struct gl_context * ctx,
-                                 struct gl_renderbuffer *wrapper,
+                                 int width, int height,
                                  gl_format format)
 {
    /*
@@ -433,18 +404,8 @@ intel_create_wrapped_renderbuffer(struct gl_context * ctx,
    rb->Format = format;
    rb->InternalFormat = rb->_BaseFormat;
    rb->DataType = intel_mesa_format_to_rb_datatype(format);
-   rb->Width = wrapper->Width;
-   rb->Height = wrapper->Height;
-
-   rb->AllocStorage = intel_nop_alloc_storage;
-   rb->Delete = intel_delete_renderbuffer;
-   rb->GetPointer = intel_get_pointer;
-
-   /*
-    * A refcount here would cause a cyclic reference. The wrapper references
-    * the unwrapper.
-    */
-   rb->Wrapped = wrapper;
+   rb->Width = width;
+   rb->Height = height;
 
    return rb;
 }
@@ -487,7 +448,7 @@ intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
                        struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
 {
    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
-      intel_draw_buffer(ctx, fb);
+      intel_draw_buffer(ctx);
    }
    else {
       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
@@ -508,62 +469,105 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx,
    intel_flush(ctx);
 
    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
-   intel_draw_buffer(ctx, fb);
+   intel_draw_buffer(ctx);
 }
 
+static bool
+intel_update_tex_wrapper_regions(struct intel_context *intel,
+                                struct intel_renderbuffer *irb,
+                                struct intel_texture_image *intel_image);
 
-static GLboolean
+static bool
 intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, 
                     struct gl_texture_image *texImage)
 {
    struct intel_context *intel = intel_context(ctx);
    struct intel_texture_image *intel_image = intel_texture_image(texImage);
+   int width, height, depth;
 
    if (!intel_span_supports_format(texImage->TexFormat)) {
       DBG("Render to texture BAD FORMAT %s\n",
          _mesa_get_format_name(texImage->TexFormat));
-      return GL_FALSE;
+      return false;
    } else {
       DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
    }
 
+   intel_miptree_get_dimensions_for_image(texImage, &width, &height, &depth);
+
    irb->Base.Format = texImage->TexFormat;
    irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
    irb->Base.InternalFormat = texImage->InternalFormat;
    irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
-   irb->Base.Width = texImage->Width;
-   irb->Base.Height = texImage->Height;
+   irb->Base.Width = width;
+   irb->Base.Height = height;
 
    irb->Base.Delete = intel_delete_renderbuffer;
    irb->Base.AllocStorage = intel_nop_alloc_storage;
 
+   if (intel_image->stencil_rb) {
+      /*  The tex image has packed depth/stencil format, but is using separate
+       * stencil. */
+
+      bool ok;
+      struct intel_renderbuffer *depth_irb =
+        intel_renderbuffer(intel_image->depth_rb);
+
+      /* Update the hiz region if necessary. */
+      ok =  intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
+      if (!ok) {
+        return false;
+      }
+
+      /* The tex image shares its embedded depth and stencil renderbuffers with
+       * the renderbuffer wrapper. */
+      _mesa_reference_renderbuffer(&irb->wrapped_depth,
+                                  intel_image->depth_rb);
+      _mesa_reference_renderbuffer(&irb->wrapped_stencil,
+                                  intel_image->stencil_rb);
+
+      return true;
+   } else {
+      return intel_update_tex_wrapper_regions(intel, irb, intel_image);
+   }
+}
+
+/**
+ * FIXME: The handling of the hiz region is broken for mipmapped depth textures
+ * FIXME: because intel_finalize_mipmap_tree is unaware of it.
+ */
+static bool
+intel_update_tex_wrapper_regions(struct intel_context *intel,
+                                struct intel_renderbuffer *irb,
+                                struct intel_texture_image *intel_image)
+{
+   struct gl_renderbuffer *rb = &irb->Base;
+
    /* Point the renderbuffer's region to the texture's region. */
    if (irb->region != intel_image->mt->region) {
-      intel_region_release(&irb->region);
       intel_region_reference(&irb->region, intel_image->mt->region);
    }
 
    /* Allocate the texture's hiz region if necessary. */
-   if (intel->vtbl.is_hiz_depth_format(intel, texImage->TexFormat)
+   if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
        && !intel_image->mt->hiz_region) {
       intel_image->mt->hiz_region =
          intel_region_alloc(intel->intelScreen,
                             I915_TILING_Y,
-                            _mesa_get_format_bytes(texImage->TexFormat),
-                            texImage->Width,
-                            texImage->Height,
-                            GL_TRUE);
+                            _mesa_get_format_bytes(rb->Format),
+                            rb->Width,
+                            rb->Height,
+                            true);
       if (!intel_image->mt->hiz_region)
-         return GL_FALSE;
+         return false;
    }
 
    /* Point the renderbuffer's hiz region to the texture's hiz region. */
    if (irb->hiz_region != intel_image->mt->hiz_region) {
-      intel_region_release(&irb->hiz_region);
       intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
    }
 
-   return GL_TRUE;
+   return true;
 }
 
 
@@ -596,22 +600,20 @@ intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
    return irb;
 }
 
-static void
+void
 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
                                   struct intel_texture_image *intel_image,
                                   int zoffset)
 {
-   struct intel_mipmap_tree *mt = intel_image->mt;
    unsigned int dst_x, dst_y;
 
    /* compute offset of the particular 2D image within the texture region */
    intel_miptree_get_image_offset(intel_image->mt,
-                                 intel_image->level,
-                                 intel_image->face,
+                                 intel_image->base.Base.Level,
+                                 intel_image->base.Base.Face,
                                  zoffset,
                                  &dst_x, &dst_y);
 
-   irb->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
    irb->draw_x = dst_x;
    irb->draw_y = dst_y;
 }
@@ -652,6 +654,22 @@ intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
    }
 }
 
+#ifndef I915
+static bool
+need_tile_offset_workaround(struct brw_context *brw,
+                           struct intel_renderbuffer *irb)
+{
+   uint32_t tile_x, tile_y;
+
+   if (brw->has_surface_tile_offset)
+      return false;
+
+   intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
+
+   return tile_x != 0 || tile_y != 0;
+}
+#endif
+
 /**
  * Called by glFramebufferTexture[123]DEXT() (and other places) to
  * prepare for rendering into texture memory.  This might be called
@@ -702,11 +720,10 @@ intel_render_texture(struct gl_context * ctx,
        irb->Base.RefCount);
 
    intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
-   intel_image->used_as_render_target = GL_TRUE;
+   intel_image->used_as_render_target = true;
 
 #ifndef I915
-   if (!brw_context(ctx)->has_surface_tile_offset &&
-       (irb->draw_offset & 4095) != 0) {
+   if (need_tile_offset_workaround(brw_context(ctx), irb)) {
       /* Original gen4 hardware couldn't draw to a non-tile-aligned
        * destination in a miptree unless you actually setup your
        * renderbuffer as a miptree and used the fragile
@@ -715,34 +732,27 @@ intel_render_texture(struct gl_context * ctx,
        * into that.
        */
       struct intel_context *intel = intel_context(ctx);
-      struct intel_mipmap_tree *old_mt = intel_image->mt;
       struct intel_mipmap_tree *new_mt;
+      int width, height, depth;
+
+      intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
 
       new_mt = intel_miptree_create(intel, image->TexObject->Target,
-                                   intel_image->base.TexFormat,
-                                   intel_image->level,
-                                   intel_image->level,
-                                   intel_image->base.Width,
-                                   intel_image->base.Height,
-                                   intel_image->base.Depth,
-                                   GL_TRUE);
-
-      intel_miptree_image_copy(intel,
-                               new_mt,
-                               intel_image->face,
-                              intel_image->level,
-                              old_mt);
-
-      intel_miptree_release(intel, &intel_image->mt);
-      intel_image->mt = new_mt;
+                                   intel_image->base.Base.TexFormat,
+                                   intel_image->base.Base.Level,
+                                   intel_image->base.Base.Level,
+                                    width, height, depth,
+                                   true);
+
+      intel_miptree_copy_teximage(intel, intel_image, new_mt);
       intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
 
-      intel_region_release(&irb->region);
       intel_region_reference(&irb->region, intel_image->mt->region);
+      intel_miptree_release(&new_mt);
    }
 #endif
    /* update drawing region, etc */
-   intel_draw_buffer(ctx, fb);
+   intel_draw_buffer(ctx);
 }
 
 
@@ -764,7 +774,7 @@ intel_finish_render_texture(struct gl_context * ctx,
 
    /* Flag that this image may now be validated into the object's miptree. */
    if (intel_image)
-      intel_image->used_as_render_target = GL_FALSE;
+      intel_image->used_as_render_target = false;
 
    /* Since we've (probably) rendered to the texture and will (likely) use
     * it in the texture domain later on in this batchbuffer, flush the
@@ -791,29 +801,21 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
     * The depth and stencil renderbuffers are the same renderbuffer or wrap
     * the same texture.
     */
-   bool depth_stencil_are_same;
-   if (depthRb && stencilRb && depthRb == stencilRb)
-      depth_stencil_are_same = true;
-   else if (depthRb && stencilRb && depthRb != stencilRb
-           && (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE)
-           && (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE)
-           && (fb->Attachment[BUFFER_DEPTH].Texture->Name
-               == fb->Attachment[BUFFER_STENCIL].Texture->Name))
-      depth_stencil_are_same = true;
-   else
-      depth_stencil_are_same = false;
-
-   bool fb_has_combined_depth_stencil_format =
-     (depthRb && depthRb->Base.Format == MESA_FORMAT_S8_Z24) ||
-     (stencilRb && stencilRb->Base.Format == MESA_FORMAT_S8_Z24);
-
-   bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
-
-   if ((intel->must_use_separate_stencil || fb_has_hiz)
-        && (depth_stencil_are_same || fb_has_combined_depth_stencil_format)) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
-   } else if (!intel->has_separate_stencil && depthRb && stencilRb && !depth_stencil_are_same) {
-      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+   if (depthRb && stencilRb) {
+      bool depth_stencil_are_same;
+      if (depthRb == stencilRb)
+        depth_stencil_are_same = true;
+      else if ((fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE) &&
+              (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE) &&
+              (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
+               fb->Attachment[BUFFER_STENCIL].Texture->Name))
+        depth_stencil_are_same = true;
+      else
+        depth_stencil_are_same = false;
+
+      if (!intel->has_separate_stencil && !depth_stencil_are_same) {
+        fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+      }
    }
 
    for (i = 0; i < Elements(fb->Attachment); i++) {
@@ -893,11 +895,9 @@ intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
 
          struct gl_texture_image *texImage =
             _mesa_select_tex_image(ctx, texObj, target, dstLevel);
-         GLenum internalFormat = texImage->InternalFormat;
 
-         if (intel_copy_texsubimage(intel_context(ctx), target,
+         if (intel_copy_texsubimage(intel_context(ctx),
                                     intel_texture_image(texImage),
-                                    internalFormat,
                                     dstX0, dstY0,
                                     srcX0, srcY0,
                                     srcX1 - srcX0, /* width */