Exemplo n.º 1
0
/**
 * \brief Call this after drawing to mark which buffers need resolving
 *
 * If the depth buffer was written to and if it has an accompanying HiZ
 * buffer, then mark that it needs a depth resolve.
 *
 * If the color buffer is a multisample window system buffer, then
 * mark that it needs a downsample.
 *
 * Also mark any render targets which will be textured as needing a render
 * cache flush.
 */
static void
brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_framebuffer *fb = ctx->DrawBuffer;

   struct intel_renderbuffer *front_irb = NULL;
   struct intel_renderbuffer *back_irb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
   struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct gl_renderbuffer_attachment *depth_att = &fb->Attachment[BUFFER_DEPTH];

   if (_mesa_is_front_buffer_drawing(fb))
      front_irb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);

   if (front_irb)
      front_irb->need_downsample = true;
   if (back_irb)
      back_irb->need_downsample = true;
   if (depth_irb && ctx->Depth.Mask) {
      intel_renderbuffer_att_set_needs_depth_resolve(depth_att);
      brw_render_cache_set_add_bo(brw, depth_irb->mt->bo);
   }

   if (ctx->Extensions.ARB_stencil_texturing &&
       stencil_irb && ctx->Stencil._WriteEnabled) {
      brw_render_cache_set_add_bo(brw, stencil_irb->mt->bo);
   }

   for (unsigned i = 0; i < fb->_NumColorDrawBuffers; i++) {
      struct intel_renderbuffer *irb =
         intel_renderbuffer(fb->_ColorDrawBuffers[i]);

      if (irb)
         brw_render_cache_set_add_bo(brw, irb->mt->bo);
   }
}
Exemplo n.º 2
0
bool
brw_blorp_clear_color(struct intel_context *intel, struct gl_framebuffer *fb)
{
   struct gl_context *ctx = &intel->ctx;
   struct brw_context *brw = brw_context(ctx);

   /* The constant color clear code doesn't work for multisampled surfaces, so
    * we need to support falling back to other clear mechanisms.
    * Unfortunately, our clear code is based on a bitmask that doesn't
    * distinguish individual color attachments, so we walk the attachments to
    * see if any require fallback, and fall back for all if any of them need
    * to.
    */
   for (unsigned buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
      struct intel_renderbuffer *irb = intel_renderbuffer(rb);

      if (irb && irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_NONE)
         return false;
   }

   for (unsigned buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];

      /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
       * the framebuffer can be complete with some attachments missing.  In
       * this case the _ColorDrawBuffers pointer will be NULL.
       */
      if (rb == NULL)
         continue;

      brw_blorp_clear_params params(brw, fb, rb, ctx->Color.ColorMask[buf]);
      brw_blorp_exec(intel, &params);
   }

   return true;
}
Exemplo n.º 3
0
static void
intelCopyTexSubImage(struct gl_context *ctx, GLuint dims,
                     struct gl_texture_image *texImage,
                     GLint xoffset, GLint yoffset, GLint slice,
                     struct gl_renderbuffer *rb,
                     GLint x, GLint y,
                     GLsizei width, GLsizei height)
{
   struct intel_context *intel = intel_context(ctx);

   /* Try the BLT engine. */
   if (intel_copy_texsubimage(intel,
                              intel_texture_image(texImage),
                              xoffset, yoffset, slice,
                              intel_renderbuffer(rb), x, y, width, height)) {
      return;
   }

   /* Otherwise, fall back to meta.  This will likely be slow. */
   perf_debug("%s - fallback to swrast\n", __FUNCTION__);
   _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
                              xoffset, yoffset, slice,
                              rb, x, y, width, height);
}
Exemplo n.º 4
0
bool
brw_blorp_clear_color(struct brw_context *brw, struct gl_framebuffer *fb,
                      bool partial_clear)
{
   struct gl_context *ctx = &brw->ctx;

   /* The constant color clear code doesn't work for multisampled surfaces, so
    * we need to support falling back to other clear mechanisms.
    * Unfortunately, our clear code is based on a bitmask that doesn't
    * distinguish individual color attachments, so we walk the attachments to
    * see if any require fallback, and fall back for all if any of them need
    * to.
    */
   for (unsigned buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
      struct intel_renderbuffer *irb = intel_renderbuffer(rb);

      if (irb && irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_NONE)
         return false;
   }

   for (unsigned buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
      struct intel_renderbuffer *irb = intel_renderbuffer(rb);

      /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
       * the framebuffer can be complete with some attachments missing.  In
       * this case the _ColorDrawBuffers pointer will be NULL.
       */
      if (rb == NULL)
         continue;

      brw_blorp_clear_params params(brw, fb, rb, ctx->Color.ColorMask[buf],
                                    partial_clear);

      bool is_fast_clear =
         (params.fast_clear_op == GEN7_FAST_CLEAR_OP_FAST_CLEAR);
      if (is_fast_clear) {
         /* Record the clear color in the miptree so that it will be
          * programmed in SURFACE_STATE by later rendering and resolve
          * operations.
          */
         uint32_t new_color_value =
            compute_fast_clear_color_bits(&ctx->Color.ClearColor);
         if (irb->mt->fast_clear_color_value != new_color_value) {
            irb->mt->fast_clear_color_value = new_color_value;
            brw->state.dirty.brw |= BRW_NEW_SURFACES;
         }

         /* If the buffer is already in INTEL_MCS_STATE_CLEAR, the clear is
          * redundant and can be skipped.
          */
         if (irb->mt->mcs_state == INTEL_MCS_STATE_CLEAR)
            continue;

         /* If the MCS buffer hasn't been allocated yet, we need to allocate
          * it now.
          */
         if (!irb->mt->mcs_mt) {
            if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt)) {
               /* MCS allocation failed--probably this will only happen in
                * out-of-memory conditions.  But in any case, try to recover
                * by falling back to a non-blorp clear technique.
                */
               return false;
            }
            brw->state.dirty.brw |= BRW_NEW_SURFACES;
         }
      }

      DBG("%s to mt %p level %d layer %d\n", __FUNCTION__,
          irb->mt, irb->mt_level, irb->mt_layer);

      brw_blorp_exec(brw, &params);

      if (is_fast_clear) {
         /* Now that the fast clear has occurred, put the buffer in
          * INTEL_MCS_STATE_CLEAR so that we won't waste time doing redundant
          * clears.
          */
         irb->mt->mcs_state = INTEL_MCS_STATE_CLEAR;
      }
   }

   return true;
}
Exemplo n.º 5
0
/**
 * Sets up a surface state structure to point at the given region.
 * While it is only used for the front/back buffer currently, it should be
 * usable for further buffers when doing ARB_draw_buffer support.
 */
static void
brw_update_renderbuffer_surface(struct brw_context *brw,
				struct gl_renderbuffer *rb,
				unsigned int unit)
{
   struct intel_context *intel = &brw->intel;
   GLcontext *ctx = &intel->ctx;
   dri_bo *region_bo = NULL;
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   struct intel_region *region = irb ? irb->region : NULL;
   struct {
      unsigned int surface_type;
      unsigned int surface_format;
      unsigned int width, height, pitch, cpp;
      GLubyte color_mask[4];
      GLboolean color_blend;
      uint32_t tiling;
      uint32_t draw_x;
      uint32_t draw_y;
   } key;

   memset(&key, 0, sizeof(key));

   if (region != NULL) {
      region_bo = region->buffer;

      key.surface_type = BRW_SURFACE_2D;
      switch (irb->Base.Format) {
      /* XRGB and ARGB are treated the same here because the chips in this
       * family cannot render to XRGB targets.  This means that we have to
       * mask writes to alpha (ala glColorMask) and reconfigure the alpha
       * blending hardware to use GL_ONE (or GL_ZERO) for cases where
       * GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is used.
       */
      case MESA_FORMAT_ARGB8888:
      case MESA_FORMAT_XRGB8888:
	 key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
	 break;
      case MESA_FORMAT_RGB565:
	 key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
	 break;
      case MESA_FORMAT_ARGB1555:
	 key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
	 break;
      case MESA_FORMAT_ARGB4444:
	 key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
	 break;
      default:
	 _mesa_problem(ctx, "Bad renderbuffer format: %d\n", irb->Base.Format);
      }
      key.tiling = region->tiling;
      if (brw->intel.intelScreen->driScrnPriv->dri2.enabled) {
	 key.width = rb->Width;
	 key.height = rb->Height;
      } else {
	 key.width = region->width;
	 key.height = region->height;
      }
      key.pitch = region->pitch;
      key.cpp = region->cpp;
      key.draw_x = region->draw_x;
      key.draw_y = region->draw_y;
   } else {
      key.surface_type = BRW_SURFACE_NULL;
      key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
      key.tiling = I915_TILING_X;
      key.width = 1;
      key.height = 1;
      key.cpp = 4;
      key.draw_x = 0;
      key.draw_y = 0;
   }

   if (intel->gen < 6) {
      /* _NEW_COLOR */
      memcpy(key.color_mask, ctx->Color.ColorMask[unit],
	     sizeof(key.color_mask));

      /* As mentioned above, disable writes to the alpha component when the
       * renderbuffer is XRGB.
       */
      if (ctx->DrawBuffer->Visual.alphaBits == 0)
	 key.color_mask[3] = GL_FALSE;

      key.color_blend = (!ctx->Color._LogicOpEnabled &&
			 (ctx->Color.BlendEnabled & (1 << unit)));
   }

   dri_bo_unreference(brw->wm.surf_bo[unit]);
   brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache,
					    BRW_SS_SURFACE,
					    &key, sizeof(key),
					    &region_bo, 1,
					    NULL);

   if (brw->wm.surf_bo[unit] == NULL) {
      struct brw_surface_state surf;

      memset(&surf, 0, sizeof(surf));

      surf.ss0.surface_format = key.surface_format;
      surf.ss0.surface_type = key.surface_type;
      if (key.tiling == I915_TILING_NONE) {
	 surf.ss1.base_addr = (key.draw_x + key.draw_y * key.pitch) * key.cpp;
      } else {
	 uint32_t tile_base, tile_x, tile_y;
	 uint32_t pitch = key.pitch * key.cpp;

	 if (key.tiling == I915_TILING_X) {
	    tile_x = key.draw_x % (512 / key.cpp);
	    tile_y = key.draw_y % 8;
	    tile_base = ((key.draw_y / 8) * (8 * pitch));
	    tile_base += (key.draw_x - tile_x) / (512 / key.cpp) * 4096;
	 } else {
	    /* Y */
	    tile_x = key.draw_x % (128 / key.cpp);
	    tile_y = key.draw_y % 32;
	    tile_base = ((key.draw_y / 32) * (32 * pitch));
	    tile_base += (key.draw_x - tile_x) / (128 / key.cpp) * 4096;
	 }
	 assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0));
	 assert(tile_x % 4 == 0);
	 assert(tile_y % 2 == 0);
	 /* Note that the low bits of these fields are missing, so
	  * there's the possibility of getting in trouble.
	  */
	 surf.ss1.base_addr = tile_base;
	 surf.ss5.x_offset = tile_x / 4;
	 surf.ss5.y_offset = tile_y / 2;
      }
      if (region_bo != NULL)
	 surf.ss1.base_addr += region_bo->offset; /* reloc */

      surf.ss2.width = key.width - 1;
      surf.ss2.height = key.height - 1;
      brw_set_surface_tiling(&surf, key.tiling);
      surf.ss3.pitch = (key.pitch * key.cpp) - 1;

      if (intel->gen < 6) {
	 /* _NEW_COLOR */
	 surf.ss0.color_blend = key.color_blend;
	 surf.ss0.writedisable_red =   !key.color_mask[0];
	 surf.ss0.writedisable_green = !key.color_mask[1];
	 surf.ss0.writedisable_blue =  !key.color_mask[2];
	 surf.ss0.writedisable_alpha = !key.color_mask[3];
      }

      /* Key size will never match key size for textures, so we're safe. */
      brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache,
                                               BRW_SS_SURFACE,
                                               &key, sizeof(key),
					       &region_bo, 1,
					       &surf, sizeof(surf));
      if (region_bo != NULL) {
	 /* We might sample from it, and we might render to it, so flag
	  * them both.  We might be able to figure out from other state
	  * a more restrictive relocation to emit.
	  */
	 drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit],
				 offsetof(struct brw_surface_state, ss1),
				 region_bo,
				 surf.ss1.base_addr - region_bo->offset,
				 I915_GEM_DOMAIN_RENDER,
				 I915_GEM_DOMAIN_RENDER);
      }
   }
/**
 * Do additional "completeness" testing of a framebuffer object.
 */
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
   struct intel_context *intel = intel_context(ctx);
   const struct intel_renderbuffer *depthRb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   const struct intel_renderbuffer *stencilRb =
      intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
   int i;

   DBG("%s() on fb %p (%s)\n", __FUNCTION__,
       fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
	    (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));

   if (depthRb)
      depth_mt = depthRb->mt;
   if (stencilRb) {
      stencil_mt = stencilRb->mt;
      if (stencil_mt->stencil_mt)
	 stencil_mt = stencil_mt->stencil_mt;
   }

   if (depth_mt && stencil_mt) {
      if (depth_mt == stencil_mt) {
	 /* For true packed depth/stencil (not faked on prefers-separate-stencil
	  * hardware) we need to be sure they're the same level/layer, since
	  * we'll be emitting a single packet describing the packed setup.
	  */
	 if (depthRb->mt_level != stencilRb->mt_level ||
	     depthRb->mt_layer != stencilRb->mt_layer) {
	    DBG("depth image level/layer %d/%d != stencil image %d/%d\n",
		depthRb->mt_level,
		depthRb->mt_layer,
		stencilRb->mt_level,
		stencilRb->mt_layer);
	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
	 }
      } else {
	 if (!intel->has_separate_stencil) {
	    DBG("separate stencil unsupported\n");
	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
	 }
	 if (stencil_mt->format != MESA_FORMAT_S8) {
	    DBG("separate stencil is %s instead of S8\n",
		_mesa_get_format_name(stencil_mt->format));
	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
	 }
	 if (intel->gen < 7 && depth_mt->hiz_mt == NULL) {
	    /* Before Gen7, separate depth and stencil buffers can be used
	     * only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
	     * Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
	     *     [DevSNB]: This field must be set to the same value (enabled
	     *     or disabled) as Hierarchical Depth Buffer Enable.
	     */
	    DBG("separate stencil without HiZ\n");
	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
	 }
      }
   }

   for (i = 0; i < Elements(fb->Attachment); i++) {
      struct gl_renderbuffer *rb;
      struct intel_renderbuffer *irb;

      if (fb->Attachment[i].Type == GL_NONE)
	 continue;

      /* A supported attachment will have a Renderbuffer set either
       * from being a Renderbuffer or being a texture that got the
       * intel_wrap_texture() treatment.
       */
      rb = fb->Attachment[i].Renderbuffer;
      if (rb == NULL) {
	 DBG("attachment without renderbuffer\n");
	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
	 continue;
      }

      if (fb->Attachment[i].Type == GL_TEXTURE) {
	 const struct gl_texture_image *img =
	    _mesa_get_attachment_teximage_const(&fb->Attachment[i]);

	 if (img->Border) {
	    DBG("texture with border\n");
	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
	    continue;
	 }
      }

      irb = intel_renderbuffer(rb);
      if (irb == NULL) {
	 DBG("software rendering renderbuffer\n");
	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
	 continue;
      }

      if (!intel->vtbl.render_target_supported(intel, rb)) {
	 DBG("Unsupported HW texture/renderbuffer format attached: %s\n",
	     _mesa_get_format_name(intel_rb_format(irb)));
	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
      }
   }
}
Exemplo n.º 7
0
/**
 * Update the hardware state for drawing into a window or framebuffer object.
 *
 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
 * places within the driver.
 *
 * Basically, this needs to be called any time the current framebuffer
 * changes, the renderbuffers change, or we need to draw into different
 * color buffers.
 */
void
intel_draw_buffer(struct gl_context * ctx, struct gl_framebuffer *fb)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
   struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;

   if (!fb) {
      /* this can happen during the initial context initialization */
      return;
   }

   /* Do this here, not core Mesa, since this function is called from
    * many places within the driver.
    */
   if (ctx->NewState & _NEW_BUFFERS) {
      /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
      _mesa_update_framebuffer(ctx);
      /* this updates the DrawBuffer's Width/Height if it's a FBO */
      _mesa_update_draw_buffer_bounds(ctx);
   }

   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      /* this may occur when we're called by glBindFrameBuffer() during
       * the process of someone setting up renderbuffers, etc.
       */
      /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
      return;
   }

   /* How many color buffers are we drawing into?
    *
    * If there are zero buffers or the buffer is too big, don't configure any
    * regions for hardware drawing.  We'll fallback to software below.  Not
    * having regions set makes some of the software fallback paths faster.
    */
   if ((fb->Width > ctx->Const.MaxRenderbufferSize)
       || (fb->Height > ctx->Const.MaxRenderbufferSize)
       || (fb->_NumColorDrawBuffers == 0)) {
      /* writing to 0  */
      colorRegions[0] = NULL;
   }
   else if (fb->_NumColorDrawBuffers > 1) {
       int i;
       struct intel_renderbuffer *irb;

       for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
           irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
           colorRegions[i] = irb ? irb->region : NULL;
       }
   }
   else {
      /* Get the intel_renderbuffer for the single colorbuffer we're drawing
       * into.
       */
      if (fb->Name == 0) {
	 /* drawing to window system buffer */
	 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT)
	    colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
	 else
	    colorRegions[0] = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
      }
      else {
	 /* drawing to user-created FBO */
	 struct intel_renderbuffer *irb;
	 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
	 colorRegions[0] = (irb && irb->region) ? irb->region : NULL;
      }
   }

   if (!colorRegions[0]) {
      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
   }
   else {
      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
   }

   /***
    *** Get depth buffer region and check if we need a software fallback.
    *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
    ***/
   if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
      irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
      if (irbDepth && irbDepth->region) {
         FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
         depthRegion = irbDepth->region;
      }
      else {
         FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
         depthRegion = NULL;
      }
   }
   else {
      /* not using depth buffer */
      FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
      depthRegion = NULL;
   }

   /***
    *** Stencil buffer
    *** This can only be hardware accelerated if we're using a
    *** combined DEPTH_STENCIL buffer.
    ***/
   if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
      irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
      if (irbStencil && irbStencil->region) {
         ASSERT(irbStencil->Base.Format == MESA_FORMAT_S8_Z24);
         FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
      }
      else {
         FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
      }
   }
   else {
      /* XXX FBO: instead of FALSE, pass ctx->Stencil._Enabled ??? */
      FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
   }

   /* If we have a (packed) stencil buffer attached but no depth buffer,
    * we still need to set up the shared depth/stencil state so we can use it.
    */
   if (depthRegion == NULL && irbStencil && irbStencil->region)
      depthRegion = irbStencil->region;

   /*
    * Update depth and stencil test state
    */
   if (ctx->Driver.Enable) {
      ctx->Driver.Enable(ctx, GL_DEPTH_TEST,
                         (ctx->Depth.Test && fb->Visual.depthBits > 0));
      ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
                         (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
   }
   else {
      /* Mesa's Stencil._Enabled field is updated when
       * _NEW_BUFFERS | _NEW_STENCIL, but i965 code assumes that the value
       * only changes with _NEW_STENCIL (which seems sensible).  So flag it
       * here since this is the _NEW_BUFFERS path.
       */
      intel->NewGLState |= (_NEW_DEPTH | _NEW_STENCIL);
   }

   intel->vtbl.set_draw_region(intel, colorRegions, depthRegion, 
                               fb->_NumColorDrawBuffers);
   intel->NewGLState |= _NEW_BUFFERS;

   /* update viewport since it depends on window size */
#ifdef I915
   intelCalcViewport(ctx);
#else
   intel->NewGLState |= _NEW_VIEWPORT;
#endif
   /* Set state we know depends on drawable parameters:
    */
   if (ctx->Driver.Scissor)
      ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
			  ctx->Scissor.Width, ctx->Scissor.Height);
   intel->NewGLState |= _NEW_SCISSOR;

   if (ctx->Driver.DepthRange)
      ctx->Driver.DepthRange(ctx,
			     ctx->Viewport.Near,
			     ctx->Viewport.Far);

   /* Update culling direction which changes depending on the
    * orientation of the buffer:
    */
   if (ctx->Driver.FrontFace)
      ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
   else
      intel->NewGLState |= _NEW_POLYGON;
}
Exemplo n.º 8
0
/**
 * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc.
 */
static GLboolean
do_blit_copypixels(struct gl_context * ctx,
                   GLint srcx, GLint srcy,
                   GLsizei width, GLsizei height,
                   GLint dstx, GLint dsty, GLenum type)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct gl_framebuffer *read_fb = ctx->ReadBuffer;
   GLint orig_dstx;
   GLint orig_dsty;
   GLint orig_srcx;
   GLint orig_srcy;
   GLboolean flip = GL_FALSE;
   struct intel_renderbuffer *draw_irb = NULL;
   struct intel_renderbuffer *read_irb = NULL;

   /* Update draw buffer bounds */
   _mesa_update_state(ctx);

   switch (type) {
   case GL_COLOR:
      if (fb->_NumColorDrawBuffers != 1) {
	 fallback_debug("glCopyPixels() fallback: MRT\n");
	 return GL_FALSE;
      }

      draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
      read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer);
      break;
   case GL_DEPTH_STENCIL_EXT:
      draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
      read_irb =
	 intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer);
      break;
   case GL_DEPTH:
      fallback_debug("glCopyPixels() fallback: GL_DEPTH\n");
      return GL_FALSE;
   case GL_STENCIL:
      fallback_debug("glCopyPixels() fallback: GL_STENCIL\n");
      return GL_FALSE;
   default:
      fallback_debug("glCopyPixels(): Unknown type\n");
      return GL_FALSE;
   }

   if (!draw_irb) {
      fallback_debug("glCopyPixels() fallback: missing draw buffer\n");
      return GL_FALSE;
   }

   if (!read_irb) {
      fallback_debug("glCopyPixels() fallback: missing read buffer\n");
      return GL_FALSE;
   }

   if (draw_irb->Base.Format != read_irb->Base.Format &&
       !(draw_irb->Base.Format == MESA_FORMAT_XRGB8888 &&
	 read_irb->Base.Format == MESA_FORMAT_ARGB8888)) {
      fallback_debug("glCopyPixels() fallback: mismatched formats (%s -> %s\n",
		     _mesa_get_format_name(read_irb->Base.Format),
		     _mesa_get_format_name(draw_irb->Base.Format));
      return GL_FALSE;
   }

   /* Copypixels can be more than a straight copy.  Ensure all the
    * extra operations are disabled:
    */
   if (!intel_check_copypixel_blit_fragment_ops(ctx) ||
       ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
      return GL_FALSE;

   intel_prepare_render(intel);

   intel_flush(&intel->ctx);

   /* Clip to destination buffer. */
   orig_dstx = dstx;
   orig_dsty = dsty;
   if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
			     fb->_Xmax, fb->_Ymax,
			     &dstx, &dsty, &width, &height))
      goto out;
   /* Adjust src coords for our post-clipped destination origin */
   srcx += dstx - orig_dstx;
   srcy += dsty - orig_dsty;

   /* Clip to source buffer. */
   orig_srcx = srcx;
   orig_srcy = srcy;
   if (!_mesa_clip_to_region(0, 0,
			     read_fb->Width, read_fb->Height,
			     &srcx, &srcy, &width, &height))
      goto out;
   /* Adjust dst coords for our post-clipped source origin */
   dstx += srcx - orig_srcx;
   dsty += srcy - orig_srcy;

   /* Flip dest Y if it's a window system framebuffer. */
   if (fb->Name == 0) {
      /* copypixels to a window system framebuffer */
      dsty = fb->Height - dsty - height;
      flip = !flip;
   }

   /* Flip source Y if it's a window system framebuffer. */
   if (read_fb->Name == 0) {
      srcy = read_fb->Height - srcy - height;
      flip = !flip;
   }

   srcx += read_irb->draw_x;
   srcy += read_irb->draw_y;
   dstx += draw_irb->draw_x;
   dsty += draw_irb->draw_y;

   if (!intel_region_copy(intel,
			  draw_irb->region, 0, dstx, dsty,
			  read_irb->region, 0, srcx, srcy,
			  width, height, flip,
			  ctx->Color.ColorLogicOpEnabled ?
			  ctx->Color.LogicOp : GL_COPY)) {
      DBG("%s: blit failure\n", __FUNCTION__);
      return GL_FALSE;
   }

out:
   intel_check_front_buffer_rendering(intel);

   DBG("%s: success\n", __FUNCTION__);
   return GL_TRUE;
}
Exemplo n.º 9
0
static void
intel_copy_image_sub_data(struct gl_context *ctx,
                          struct gl_texture_image *src_image,
                          struct gl_renderbuffer *src_renderbuffer,
                          int src_x, int src_y, int src_z,
                          struct gl_texture_image *dst_image,
                          struct gl_renderbuffer *dst_renderbuffer,
                          int dst_x, int dst_y, int dst_z,
                          int src_width, int src_height)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_mipmap_tree *src_mt, *dst_mt;
   unsigned src_level, dst_level;

   if (src_image) {
      src_mt = intel_texture_image(src_image)->mt;
      src_level = src_image->Level + src_image->TexObject->MinLevel;

      /* Cube maps actually have different images per face */
      if (src_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
         src_z = src_image->Face;

      src_z += src_image->TexObject->MinLayer;
   } else {
      assert(src_renderbuffer);
      src_mt = intel_renderbuffer(src_renderbuffer)->mt;
      src_image = src_renderbuffer->TexImage;
      src_level = 0;
   }

   if (dst_image) {
      dst_mt = intel_texture_image(dst_image)->mt;

      dst_level = dst_image->Level + dst_image->TexObject->MinLevel;

      /* Cube maps actually have different images per face */
      if (dst_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
         dst_z = dst_image->Face;

      dst_z += dst_image->TexObject->MinLayer;
   } else {
      assert(dst_renderbuffer);
      dst_mt = intel_renderbuffer(dst_renderbuffer)->mt;
      dst_image = dst_renderbuffer->TexImage;
      dst_level = 0;
   }

   copy_miptrees(brw, src_mt, src_x, src_y, src_z, src_level,
                 dst_mt, dst_x, dst_y, dst_z, dst_level,
                 src_width, src_height);

   /* CopyImage only works for equal formats, texture view equivalence
    * classes, and a couple special cases for compressed textures.
    *
    * Notably, GL_DEPTH_STENCIL does not appear in any equivalence
    * classes, so we know the formats must be the same, and thus both
    * will either have stencil, or not.  They can't be mismatched.
    */
   assert((src_mt->stencil_mt != NULL) == (dst_mt->stencil_mt != NULL));

   if (dst_mt->stencil_mt) {
      copy_miptrees(brw, src_mt->stencil_mt, src_x, src_y, src_z, src_level,
                    dst_mt->stencil_mt, dst_x, dst_y, dst_z, dst_level,
                    src_width, src_height);
   }
}
Exemplo n.º 10
0
/**
 * Called by glFramebufferTexture[123]DEXT() (and other places) to
 * prepare for rendering into texture memory.  This might be called
 * many times to choose different texture levels, cube faces, etc
 * before intel_finish_render_texture() is ever called.
 */
static void
intel_render_texture(GLcontext * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct gl_texture_image *newImage
      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image;
   GLuint dst_x, dst_y;

   (void) fb;

   ASSERT(newImage);

   intel_image = intel_texture_image(newImage);
   if (!intel_image->mt) {
      /* Fallback on drawing to a texture that doesn't have a miptree
       * (has a border, width/height 0, etc.)
       */
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      _mesa_render_texture(ctx, fb, att);
      return;
   }
   else if (!irb) {
      irb = intel_wrap_texture(ctx, newImage);
      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
      }
      else {
         /* fallback to software rendering */
         _mesa_render_texture(ctx, fb, att);
         return;
      }
   }

   if (!intel_update_wrapper(ctx, irb, newImage)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _mesa_render_texture(ctx, fb, att);
       return;
   }

   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
       _glthread_GetID(),
       att->Texture->Name, newImage->Width, newImage->Height,
       irb->Base.RefCount);

   /* point the renderbufer's region to the texture image region */
   if (irb->region != intel_image->mt->region) {
      if (irb->region)
	 intel_region_release(&irb->region);
      intel_region_reference(&irb->region, intel_image->mt->region);
   }

   /* compute offset of the particular 2D image within the texture region */
   intel_miptree_get_image_offset(intel_image->mt,
				  att->TextureLevel,
				  att->CubeMapFace,
				  att->Zoffset,
				  &dst_x, &dst_y);

   intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch +
					   dst_x) * intel_image->mt->cpp;
   intel_image->mt->region->draw_x = dst_x;
   intel_image->mt->region->draw_y = dst_y;
   intel_image->used_as_render_target = GL_TRUE;

   /* update drawing region, etc */
   intel_draw_buffer(ctx, fb);
}
Exemplo n.º 11
0
/**
 * \brief A fast path for glReadPixels
 *
 * This fast path is taken when the source format is BGRA, RGBA,
 * A or L and when the texture memory is X- or Y-tiled.  It downloads
 * the source data by directly mapping the memory without a GTT fence.
 * This then needs to be de-tiled on the CPU before presenting the data to
 * the user in the linear fasion.
 *
 * This is a performance win over the conventional texture download path.
 * In the conventional texture download path, the texture is either mapped
 * through the GTT or copied to a linear buffer with the blitter before
 * handing off to a software path.  This allows us to avoid round-tripping
 * through the GPU (in the case where we would be blitting) and do only a
 * single copy operation.
 */
static bool
intel_readpixels_tiled_memcpy(struct gl_context * ctx,
                              GLint xoffset, GLint yoffset,
                              GLsizei width, GLsizei height,
                              GLenum format, GLenum type,
                              GLvoid * pixels,
                              const struct gl_pixelstore_attrib *pack)
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
   const struct gen_device_info *devinfo = &brw->screen->devinfo;

   /* This path supports reading from color buffers only */
   if (rb == NULL)
      return false;

   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   int dst_pitch;

   /* The miptree's buffer. */
   struct brw_bo *bo;

   uint32_t cpp;
   mem_copy_fn mem_copy = NULL;

   /* This fastpath is restricted to specific renderbuffer types:
    * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
    * more types.
    */
   if (!devinfo->has_llc ||
       !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
       pixels == NULL ||
       _mesa_is_bufferobj(pack->BufferObj) ||
       pack->Alignment > 4 ||
       pack->SkipPixels > 0 ||
       pack->SkipRows > 0 ||
       (pack->RowLength != 0 && pack->RowLength != width) ||
       pack->SwapBytes ||
       pack->LsbFirst ||
       pack->Invert)
      return false;

   /* Only a simple blit, no scale, bias or other mapping. */
   if (ctx->_ImageTransferState)
      return false;

   /* It is possible that the renderbuffer (or underlying texture) is
    * multisampled.  Since ReadPixels from a multisampled buffer requires a
    * multisample resolve, we can't handle this here
    */
   if (rb->NumSamples > 1)
      return false;

   /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
    * function doesn't set the last channel to 1. Note this checks BaseFormat
    * rather than TexFormat in case the RGBX format is being simulated with an
    * RGBA format.
    */
   if (rb->_BaseFormat == GL_RGB)
      return false;

   if (!intel_get_memcpy(rb->Format, format, type, &mem_copy, &cpp))
      return false;

   if (!irb->mt ||
       (irb->mt->surf.tiling != ISL_TILING_X &&
        irb->mt->surf.tiling != ISL_TILING_Y0)) {
      /* The algorithm is written only for X- or Y-tiled memory. */
      return false;
   }

   /* tiled_to_linear() assumes that if the object is swizzled, it is using
    * I915_BIT6_SWIZZLE_9_10 for X and I915_BIT6_SWIZZLE_9 for Y.  This is only
    * true on gen5 and above.
    *
    * The killer on top is that some gen4 have an L-shaped swizzle mode, where
    * parts of the memory aren't swizzled at all. Userspace just can't handle
    * that.
    */
   if (devinfo->gen < 5 && brw->has_swizzling)
      return false;

   /* Since we are going to read raw data to the miptree, we need to resolve
    * any pending fast color clears before we start.
    */
   intel_miptree_access_raw(brw, irb->mt, irb->mt_level, irb->mt_layer, false);

   bo = irb->mt->bo;

   if (brw_batch_references(&brw->batch, bo)) {
      perf_debug("Flushing before mapping a referenced bo.\n");
      intel_batchbuffer_flush(brw);
   }

   void *map = brw_bo_map(brw, bo, MAP_READ | MAP_RAW);
   if (map == NULL) {
      DBG("%s: failed to map bo\n", __func__);
      return false;
   }

   unsigned slice_offset_x, slice_offset_y;
   intel_miptree_get_image_offset(irb->mt, irb->mt_level, irb->mt_layer,
                                  &slice_offset_x, &slice_offset_y);
   xoffset += slice_offset_x;
   yoffset += slice_offset_y;

   dst_pitch = _mesa_image_row_stride(pack, width, format, type);

   /* For a window-system renderbuffer, the buffer is actually flipped
    * vertically, so we need to handle that.  Since the detiling function
    * can only really work in the forwards direction, we have to be a
    * little creative.  First, we compute the Y-offset of the first row of
    * the renderbuffer (in renderbuffer coordinates).  We then match that
    * with the last row of the client's data.  Finally, we give
    * tiled_to_linear a negative pitch so that it walks through the
    * client's data backwards as it walks through the renderbufer forwards.
    */
   if (rb->Name == 0) {
      yoffset = rb->Height - yoffset - height;
      pixels += (ptrdiff_t) (height - 1) * dst_pitch;
      dst_pitch = -dst_pitch;
   }

   /* We postponed printing this message until having committed to executing
    * the function.
    */
   DBG("%s: x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
       "mesa_format=0x%x tiling=%d "
       "pack=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n",
       __func__, xoffset, yoffset, width, height,
       format, type, rb->Format, irb->mt->surf.tiling,
       pack->Alignment, pack->RowLength, pack->SkipPixels,
       pack->SkipRows);

   tiled_to_linear(
      xoffset * cpp, (xoffset + width) * cpp,
      yoffset, yoffset + height,
      pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp,
      map + irb->mt->offset,
      dst_pitch, irb->mt->surf.row_pitch,
      brw->has_swizzling,
      irb->mt->surf.tiling,
      mem_copy
   );

   brw_bo_unmap(bo);
   return true;
}
/**
 * Do additional "completeness" testing of a framebuffer object.
 */
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_renderbuffer *depthRb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencilRb =
      intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
   int i;

   DBG("%s() on fb %p (%s)\n", __FUNCTION__,
       fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
	    (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));

   if (depthRb)
      depth_mt = depthRb->mt;
   if (stencilRb) {
      stencil_mt = stencilRb->mt;
      if (stencil_mt->stencil_mt)
	 stencil_mt = stencil_mt->stencil_mt;
   }

   if (depth_mt && stencil_mt) {
      if (brw->gen >= 7) {
         /* For gen >= 7, we are using the lod/minimum-array-element fields
          * and supportting layered rendering. This means that we must restrict
          * the depth & stencil attachments to match in various more retrictive
          * ways. (width, height, depth, LOD and layer)
          */
	 if (depth_mt->physical_width0 != stencil_mt->physical_width0 ||
             depth_mt->physical_height0 != stencil_mt->physical_height0 ||
             depth_mt->physical_depth0 != stencil_mt->physical_depth0 ||
             depthRb->mt_level != stencilRb->mt_level ||
	     depthRb->mt_layer != stencilRb->mt_layer) {
	    fbo_incomplete(fb,
                           "FBO incomplete: depth and stencil must match in"
                           "width, height, depth, LOD and layer\n");
	 }
      }
      if (depth_mt == stencil_mt) {
	 /* For true packed depth/stencil (not faked on prefers-separate-stencil
	  * hardware) we need to be sure they're the same level/layer, since
	  * we'll be emitting a single packet describing the packed setup.
	  */
	 if (depthRb->mt_level != stencilRb->mt_level ||
	     depthRb->mt_layer != stencilRb->mt_layer) {
	    fbo_incomplete(fb,
                           "FBO incomplete: depth image level/layer %d/%d != "
                           "stencil image %d/%d\n",
                           depthRb->mt_level,
                           depthRb->mt_layer,
                           stencilRb->mt_level,
                           stencilRb->mt_layer);
	 }
      } else {
	 if (!brw->has_separate_stencil) {
	    fbo_incomplete(fb, "FBO incomplete: separate stencil "
                           "unsupported\n");
	 }
	 if (stencil_mt->format != MESA_FORMAT_S8) {
	    fbo_incomplete(fb, "FBO incomplete: separate stencil is %s "
                           "instead of S8\n",
                           _mesa_get_format_name(stencil_mt->format));
	 }
	 if (brw->gen < 7 && !intel_renderbuffer_has_hiz(depthRb)) {
	    /* Before Gen7, separate depth and stencil buffers can be used
	     * only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
	     * Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
	     *     [DevSNB]: This field must be set to the same value (enabled
	     *     or disabled) as Hierarchical Depth Buffer Enable.
	     */
	    fbo_incomplete(fb, "FBO incomplete: separate stencil "
                           "without HiZ\n");
	 }
      }
   }

   for (i = 0; i < Elements(fb->Attachment); i++) {
      struct gl_renderbuffer *rb;
      struct intel_renderbuffer *irb;

      if (fb->Attachment[i].Type == GL_NONE)
	 continue;

      /* A supported attachment will have a Renderbuffer set either
       * from being a Renderbuffer or being a texture that got the
       * intel_wrap_texture() treatment.
       */
      rb = fb->Attachment[i].Renderbuffer;
      if (rb == NULL) {
	 fbo_incomplete(fb, "FBO incomplete: attachment without "
                        "renderbuffer\n");
	 continue;
      }

      if (fb->Attachment[i].Type == GL_TEXTURE) {
	 if (rb->TexImage->Border) {
	    fbo_incomplete(fb, "FBO incomplete: texture with border\n");
	    continue;
	 }
      }

      irb = intel_renderbuffer(rb);
      if (irb == NULL) {
	 fbo_incomplete(fb, "FBO incomplete: software rendering "
                        "renderbuffer\n");
	 continue;
      }

      if (!brw_render_target_supported(brw, rb)) {
	 fbo_incomplete(fb, "FBO incomplete: Unsupported HW "
                        "texture/renderbuffer format attached: %s\n",
                        _mesa_get_format_name(intel_rb_format(irb)));
      }
   }
}
static void
intel_image_target_renderbuffer_storage(struct gl_context *ctx,
					struct gl_renderbuffer *rb,
					void *image_handle)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_renderbuffer *irb;
   __DRIscreen *screen;
   __DRIimage *image;

   screen = brw->intelScreen->driScrnPriv;
   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
					      screen->loaderPrivate);
   if (image == NULL)
      return;

   if (image->planar_format && image->planar_format->nplanes > 1) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
            "glEGLImageTargetRenderbufferStorage(planar buffers are not "
               "supported as render targets.");
      return;
   }

   /* Buffers originating from outside are for read-only. */
   if (image->dma_buf_imported) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
            "glEGLImageTargetRenderbufferStorage(dma buffers are read-only)");
      return;
   }

   /* __DRIimage is opaque to the core so it has to be checked here */
   switch (image->format) {
   case MESA_FORMAT_RGBA8888_REV:
      _mesa_error(ctx, GL_INVALID_OPERATION,
            "glEGLImageTargetRenderbufferStorage(unsupported image format");
      return;
      break;
   default:
      break;
   }

   irb = intel_renderbuffer(rb);
   intel_miptree_release(&irb->mt);
   irb->mt = intel_miptree_create_for_bo(brw,
                                         image->region->bo,
                                         image->format,
                                         image->offset,
                                         image->region->width,
                                         image->region->height,
                                         image->region->pitch,
                                         image->region->tiling);
   if (!irb->mt)
      return;

   rb->InternalFormat = image->internal_format;
   rb->Width = image->region->width;
   rb->Height = image->region->height;
   rb->Format = image->format;
   rb->_BaseFormat = _mesa_base_fbo_format(ctx, image->internal_format);
   rb->NeedsFinishRenderTexture = true;
}
Exemplo n.º 14
0
static GLboolean do_check_fallback(struct brw_context *brw)
{
   struct intel_context *intel = &brw->intel;
   GLcontext *ctx = &brw->intel.ctx;
   GLuint i;

   if (brw->intel.no_rast) {
      DBG("FALLBACK: rasterization disabled\n");
      return GL_TRUE;
   }

   /* _NEW_RENDERMODE
    */
   if (ctx->RenderMode != GL_RENDER) {
      DBG("FALLBACK: render mode\n");
      return GL_TRUE;
   }

   /* _NEW_TEXTURE:
    */
   for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
      if (texUnit->_ReallyEnabled) {
	 struct intel_texture_object *intelObj = intel_texture_object(texUnit->_Current);
	 struct gl_texture_image *texImage = intelObj->base.Image[0][intelObj->firstLevel];
	 if (texImage->Border) {
	    DBG("FALLBACK: texture border\n");
	    return GL_TRUE;
	 }
      }
   }
   
   /* _NEW_STENCIL 
    */
   if (ctx->Stencil._Enabled &&
       (ctx->DrawBuffer->Name == 0 && !brw->intel.hw_stencil)) {
      DBG("FALLBACK: stencil\n");
      return GL_TRUE;
   }

   /* _NEW_BUFFERS */
   if (IS_965(intel->intelScreen->deviceID) &&
       !IS_G4X(intel->intelScreen->deviceID)) {
      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
	 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
	 struct intel_renderbuffer *irb = intel_renderbuffer(rb);

	 /* The original gen4 hardware couldn't set up WM surfaces pointing
	  * at an offset within a tile, which can happen when rendering to
	  * anything but the base level of a texture or the +X face/0 depth.
	  * This was fixed with the 4 Series hardware.
	  *
	  * For these original chips, you would have to make the depth and
	  * color destination surfaces include information on the texture
	  * type, LOD, face, and various limits to use them as a destination.
	  * I would have done this, but there's also a nasty requirement that
	  * the depth and the color surfaces all be of the same LOD, which
	  * may be a worse requirement than this alignment.  (Also, we may
	  * want to just demote the texture to untiled, instead).
	  */
	 if (irb->region && irb->region->tiling != I915_TILING_NONE &&
	     (irb->region->draw_offset & 4095)) {
	    DBG("FALLBACK: non-tile-aligned destination for tiled FBO\n");
	    return GL_TRUE;
	 }
      }
   }

   return GL_FALSE;
}
Exemplo n.º 15
0
/**
 * Called via glRenderbufferStorageEXT() to set the format and allocate
 * storage for a user-created renderbuffer.
 */
GLboolean
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
                                 GLenum internalFormat,
                                 GLuint width, GLuint height)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   rb->NumSamples = quantize_num_samples(intel, rb->NumSamples);

   ASSERT(rb->Name != 0);

   switch (internalFormat) {
   default:
      /* Use the same format-choice logic as for textures.
       * Renderbuffers aren't any different from textures for us,
       * except they're less useful because you can't texture with
       * them.
       */
      rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
							 GL_NONE, GL_NONE);
      break;
   case GL_STENCIL_INDEX:
   case GL_STENCIL_INDEX1_EXT:
   case GL_STENCIL_INDEX4_EXT:
   case GL_STENCIL_INDEX8_EXT:
   case GL_STENCIL_INDEX16_EXT:
      /* These aren't actual texture formats, so force them here. */
      if (intel->has_separate_stencil) {
	 rb->Format = MESA_FORMAT_S8;
      } else {
	 assert(!intel->must_use_separate_stencil);
	 rb->Format = MESA_FORMAT_S8_Z24;
      }
      break;
   }

   rb->Width = width;
   rb->Height = height;
   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);

   intel_miptree_release(&irb->mt);

   DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__,
       _mesa_lookup_enum_by_nr(internalFormat),
       _mesa_get_format_name(rb->Format), width, height);

   if (width == 0 || height == 0)
      return true;

   irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format,
						   width, height,
                                                   rb->NumSamples);
   if (!irb->mt)
      return false;

   if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
      bool ok = intel_miptree_alloc_hiz(intel, irb->mt, rb->NumSamples);
      if (!ok) {
	 intel_miptree_release(&irb->mt);
	 return false;
      }
   }

   return true;
}
Exemplo n.º 16
0
/**
 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
 * We can do this when the dst renderbuffer is actually a texture and
 * there is no scaling, mirroring or scissoring.
 *
 * \return new buffer mask indicating the buffers left to blit using the
 *         normal path.
 */
static GLbitfield
intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
                                          GLint srcX0, GLint srcY0,
                                          GLint srcX1, GLint srcY1,
                                          GLint dstX0, GLint dstY0,
                                          GLint dstX1, GLint dstY1,
                                          GLbitfield mask, GLenum filter)
{
   if (mask & GL_COLOR_BUFFER_BIT) {
      GLint i;
      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
      const struct gl_renderbuffer_attachment *drawAtt;
      struct intel_renderbuffer *srcRb = 
         intel_renderbuffer(readFb->_ColorReadBuffer);

      /* If the source and destination are the same size with no mirroring,
       * the rectangles are within the size of the texture and there is no
       * scissor then we can use glCopyTexSubimage2D to implement the blit.
       * This will end up as a fast hardware blit on some drivers.
       */
      const GLboolean use_intel_copy_texsubimage =
         srcX0 - srcX1 == dstX0 - dstX1 &&
         srcY0 - srcY1 == dstY0 - dstY1 &&
         srcX1 >= srcX0 &&
         srcY1 >= srcY0 &&
         srcX0 >= 0 && srcX1 <= readFb->Width &&
         srcY0 >= 0 && srcY1 <= readFb->Height &&
         dstX0 >= 0 && dstX1 <= drawFb->Width &&
         dstY0 >= 0 && dstY1 <= drawFb->Height &&
         !ctx->Scissor.Enabled;

      /* Verify that all the draw buffers can be blitted using
       * intel_copy_texsubimage().
       */
      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
         int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
         if (idx == -1)
            continue;
         drawAtt = &drawFb->Attachment[idx];

         if (srcRb && drawAtt && drawAtt->Texture &&
             use_intel_copy_texsubimage)
            continue;
         else
            return mask;
      }

      /* Blit to all active draw buffers */
      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
         int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
         if (idx == -1)
            continue;
         drawAtt = &drawFb->Attachment[idx];

         {
            const struct gl_texture_object *texObj = drawAtt->Texture;
            const GLuint dstLevel = drawAtt->TextureLevel;
            const GLenum target = texObj->Target;

            struct gl_texture_image *texImage =
               _mesa_select_tex_image(ctx, texObj, target, dstLevel);

            if (!intel_copy_texsubimage(intel_context(ctx),
                                        intel_texture_image(texImage),
                                        dstX0, dstY0,
                                        srcRb,
                                        srcX0, srcY0,
                                        srcX1 - srcX0, /* width */
                                        srcY1 - srcY0))
               return mask;
         }
      }

      mask &= ~GL_COLOR_BUFFER_BIT;
   }

   return mask;
}
Exemplo n.º 17
0
/**
 * Called via glRenderbufferStorageEXT() to set the format and allocate
 * storage for a user-created renderbuffer.
 */
static GLboolean
intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
                                 GLenum internalFormat,
                                 GLuint width, GLuint height)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   int cpp;
   GLuint pitch;

   ASSERT(rb->Name != 0);

   switch (internalFormat) {
   case GL_R3_G3_B2:
   case GL_RGB4:
   case GL_RGB5:
      rb->Format = MESA_FORMAT_RGB565;
      rb->DataType = GL_UNSIGNED_BYTE;
      break;
   case GL_RGB:
   case GL_RGB8:
   case GL_RGB10:
   case GL_RGB12:
   case GL_RGB16:
      rb->Format = MESA_FORMAT_XRGB8888;
      rb->DataType = GL_UNSIGNED_BYTE;
      break;
   case GL_RGBA:
   case GL_RGBA2:
   case GL_RGBA4:
   case GL_RGB5_A1:
   case GL_RGBA8:
   case GL_RGB10_A2:
   case GL_RGBA12:
   case GL_RGBA16:
      rb->Format = MESA_FORMAT_ARGB8888;
      rb->DataType = GL_UNSIGNED_BYTE;
      break;
   case GL_STENCIL_INDEX:
   case GL_STENCIL_INDEX1_EXT:
   case GL_STENCIL_INDEX4_EXT:
   case GL_STENCIL_INDEX8_EXT:
   case GL_STENCIL_INDEX16_EXT:
      /* alloc a depth+stencil buffer */
      rb->Format = MESA_FORMAT_S8_Z24;
      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
      break;
   case GL_DEPTH_COMPONENT16:
      rb->Format = MESA_FORMAT_Z16;
      rb->DataType = GL_UNSIGNED_SHORT;
      break;
   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_COMPONENT24:
   case GL_DEPTH_COMPONENT32:
      rb->Format = MESA_FORMAT_S8_Z24;
      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
      break;
   case GL_DEPTH_STENCIL_EXT:
   case GL_DEPTH24_STENCIL8_EXT:
      rb->Format = MESA_FORMAT_S8_Z24;
      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format in intel_alloc_renderbuffer_storage");
      return GL_FALSE;
   }

   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
   cpp = _mesa_get_format_bytes(rb->Format);

   intelFlush(ctx);

   /* free old region */
   if (irb->region) {
      intel_region_release(&irb->region);
   }

   /* allocate new memory region/renderbuffer */

   /* Choose a pitch to match hardware requirements:
    */
   pitch = ((cpp * width + 63) & ~63) / cpp;

   /* alloc hardware renderbuffer */
   DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width, height, pitch);

   irb->region = intel_region_alloc(intel, I915_TILING_NONE, cpp,
				    width, height, pitch, GL_TRUE);
   if (!irb->region)
      return GL_FALSE;       /* out of memory? */

   ASSERT(irb->region->buffer);

   rb->Width = width;
   rb->Height = height;

   return GL_TRUE;
}
Exemplo n.º 18
0
/**
 * Do additional "completeness" testing of a framebuffer object.
 */
static void
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_renderbuffer *depthRb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencilRb =
      intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
   int i;

   DBG("%s() on fb %p (%s)\n", __FUNCTION__,
       fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
	    (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));

   if (depthRb)
      depth_mt = depthRb->mt;
   if (stencilRb)
      stencil_mt = stencilRb->mt;

   if (depth_mt && stencil_mt) {
      /* Make sure that the depth and stencil buffers are actually the same
       * slice of the same miptree, since we only support packed
       * depth/stencil.
       */
      if (depth_mt == stencil_mt) {
	 if (depthRb->mt_level != stencilRb->mt_level ||
	     depthRb->mt_layer != stencilRb->mt_layer) {
	    fbo_incomplete(fb,
                           "FBO incomplete: depth image level/layer %d/%d != "
                           "stencil image %d/%d\n",
                           depthRb->mt_level,
                           depthRb->mt_layer,
                           stencilRb->mt_level,
                           stencilRb->mt_layer);
	 }
      } else {
         fbo_incomplete(fb, "FBO incomplete: separate stencil unsupported\n");
      }
   }

   for (i = 0; i < Elements(fb->Attachment); i++) {
      struct gl_renderbuffer *rb;
      struct intel_renderbuffer *irb;

      if (fb->Attachment[i].Type == GL_NONE)
	 continue;

      /* A supported attachment will have a Renderbuffer set either
       * from being a Renderbuffer or being a texture that got the
       * intel_wrap_texture() treatment.
       */
      rb = fb->Attachment[i].Renderbuffer;
      if (rb == NULL) {
	 fbo_incomplete(fb, "FBO incomplete: attachment without "
                        "renderbuffer\n");
	 continue;
      }

      if (fb->Attachment[i].Type == GL_TEXTURE) {
	 if (rb->TexImage->Border) {
	    fbo_incomplete(fb, "FBO incomplete: texture with border\n");
	    continue;
	 }
      }

      irb = intel_renderbuffer(rb);
      if (irb == NULL) {
	 fbo_incomplete(fb, "FBO incomplete: software rendering "
                        "renderbuffer\n");
	 continue;
      }

      if (!intel->vtbl.render_target_supported(intel, rb)) {
	 fbo_incomplete(fb, "FBO incomplete: Unsupported HW "
                        "texture/renderbuffer format attached: %s\n",
                        _mesa_get_format_name(intel_rb_format(irb)));
      }
   }
}
static bool
do_blit_drawpixels(struct gl_context * ctx,
		   GLint x, GLint y, GLsizei width, GLsizei height,
		   GLenum format, GLenum type,
		   const struct gl_pixelstore_attrib *unpack,
		   const GLvoid * pixels)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   drm_intel_bo *src_buffer;

   DBG("%s\n", __FUNCTION__);

   if (!intel_check_blit_fragment_ops(ctx, false))
      return false;

   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
      DBG("%s: fallback due to MRT\n", __FUNCTION__);
      return false;
   }

   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);

   if (!_mesa_format_matches_format_and_type(irb->mt->format, format, type,
                                             false)) {
      DBG("%s: bad format for blit\n", __FUNCTION__);
      return false;
   }

   if (unpack->SwapBytes || unpack->LsbFirst ||
       unpack->SkipPixels || unpack->SkipRows) {
      DBG("%s: bad packing params\n", __FUNCTION__);
      return false;
   }

   int src_stride = _mesa_image_row_stride(unpack, width, format, type);
   bool src_flip = false;
   /* Mesa flips the src_stride for unpack->Invert, but we want our mt to have
    * a normal src_stride.
    */
   if (unpack->Invert) {
      src_stride = -src_stride;
      src_flip = true;
   }

   src_offset = (GLintptr)pixels;
   src_offset += _mesa_image_offset(2, unpack, width, height,
				    format, type, 0, 0, 0);

   intel_prepare_render(brw);

   src_buffer = intel_bufferobj_buffer(brw, src,
				       src_offset, width * height *
                                       irb->mt->cpp);

   struct intel_mipmap_tree *pbo_mt =
      intel_miptree_create_for_bo(brw,
                                  src_buffer,
                                  irb->mt->format,
                                  src_offset,
                                  width, height,
                                  src_stride, I915_TILING_NONE);
   if (!pbo_mt)
      return false;

   if (!intel_miptree_blit(brw,
                           pbo_mt, 0, 0,
                           0, 0, src_flip,
                           irb->mt, irb->mt_level, irb->mt_layer,
                           x, y, _mesa_is_winsys_fbo(ctx->DrawBuffer),
                           width, height, GL_COPY)) {
      DBG("%s: blit failed\n", __FUNCTION__);
      intel_miptree_release(&pbo_mt);
      return false;
   }

   intel_miptree_release(&pbo_mt);

   if (ctx->Query.CurrentOcclusionObject)
      ctx->Query.CurrentOcclusionObject->Result += width * height;

   intel_check_front_buffer_rendering(brw);

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
/**
 * Sets up a surface state structure to point at the given region.
 * While it is only used for the front/back buffer currently, it should be
 * usable for further buffers when doing ARB_draw_buffer support.
 */
static void
gen6_update_renderbuffer_surface(struct brw_context *brw,
                                 struct gl_renderbuffer *rb,
                                 bool layered,
                                 unsigned int unit)
{
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   struct intel_mipmap_tree *mt = irb->mt;
   uint32_t *surf;
   uint32_t format = 0;
   /* _NEW_BUFFERS */
   mesa_format rb_format = _mesa_get_render_format(ctx, intel_rb_format(irb));
   uint32_t surftype;
   int depth = MAX2(irb->layer_count, 1);
   const GLenum gl_target =
      rb->TexImage ? rb->TexImage->TexObject->Target : GL_TEXTURE_2D;

   uint32_t surf_index =
      brw->wm.prog_data->binding_table.render_target_start + unit;

   intel_miptree_used_for_rendering(irb->mt);

   surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32,
                          &brw->wm.base.surf_offset[surf_index]);

   format = brw->render_target_format[rb_format];
   if (unlikely(!brw->format_supported_as_render_target[rb_format])) {
      _mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n",
                    __func__, _mesa_get_format_name(rb_format));
   }

   switch (gl_target) {
   case GL_TEXTURE_CUBE_MAP_ARRAY:
   case GL_TEXTURE_CUBE_MAP:
      surftype = BRW_SURFACE_2D;
      depth *= 6;
      break;
   case GL_TEXTURE_3D:
      depth = MAX2(irb->mt->logical_depth0, 1);
      /* fallthrough */
   default:
      surftype = translate_tex_target(gl_target);
      break;
   }

   const int min_array_element = layered ? 0 : irb->mt_layer;

   surf[0] = SET_FIELD(surftype, BRW_SURFACE_TYPE) |
             SET_FIELD(format, BRW_SURFACE_FORMAT);

   /* reloc */
   assert(mt->offset % mt->cpp == 0);
   surf[1] = mt->bo->offset64 + mt->offset;

   /* In the gen6 PRM Volume 1 Part 1: Graphics Core, Section 7.18.3.7.1
    * (Surface Arrays For all surfaces other than separate stencil buffer):
    *
    * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than the value
    *  calculated in the equation above , for every other odd Surface Height
    *  starting from 1 i.e. 1,5,9,13"
    *
    * Since this Qpitch errata only impacts the sampler, we have to adjust the
    * input for the rendering surface to achieve the same qpitch. For the
    * affected heights, we increment the height by 1 for the rendering
    * surface.
    */
   int height0 = irb->mt->logical_height0;
   if (brw->gen == 6 && irb->mt->num_samples > 1 && (height0 % 4) == 1)
      height0++;

   surf[2] = SET_FIELD(mt->logical_width0 - 1, BRW_SURFACE_WIDTH) |
             SET_FIELD(height0 - 1, BRW_SURFACE_HEIGHT) |
             SET_FIELD(irb->mt_level - irb->mt->first_level, BRW_SURFACE_LOD);

   surf[3] = brw_get_surface_tiling_bits(mt->tiling) |
             SET_FIELD(depth - 1, BRW_SURFACE_DEPTH) |
             SET_FIELD(mt->pitch - 1, BRW_SURFACE_PITCH);

   surf[4] = brw_get_surface_num_multisamples(mt->num_samples) |
             SET_FIELD(min_array_element, BRW_SURFACE_MIN_ARRAY_ELEMENT) |
             SET_FIELD(depth - 1, BRW_SURFACE_RENDER_TARGET_VIEW_EXTENT);

   surf[5] = (mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0);

   drm_intel_bo_emit_reloc(brw->batch.bo,
			   brw->wm.base.surf_offset[surf_index] + 4,
			   mt->bo,
			   surf[1] - mt->bo->offset64,
			   I915_GEM_DOMAIN_RENDER,
			   I915_GEM_DOMAIN_RENDER);
}
Exemplo n.º 21
0
/**
 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
 * We can do this when the dst renderbuffer is actually a texture and
 * there is no scaling, mirroring or scissoring.
 *
 * \return new buffer mask indicating the buffers left to blit using the
 *         normal path.
 */
static GLbitfield
intel_blit_framebuffer_with_blitter(struct gl_context *ctx,
                                    GLint srcX0, GLint srcY0,
                                    GLint srcX1, GLint srcY1,
                                    GLint dstX0, GLint dstY0,
                                    GLint dstX1, GLint dstY1,
                                    GLbitfield mask, GLenum filter)
{
   struct brw_context *brw = brw_context(ctx);

   /* Sync up the state of window system buffers.  We need to do this before
    * we go looking for the buffers.
    */
   intel_prepare_render(brw);

   if (mask & GL_COLOR_BUFFER_BIT) {
      GLint i;
      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
      struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer;
      struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);

      if (!src_irb) {
         perf_debug("glBlitFramebuffer(): missing src renderbuffer.  "
                    "Falling back to software rendering.\n");
         return mask;
      }

      /* If the source and destination are the same size with no mirroring,
       * the rectangles are within the size of the texture and there is no
       * scissor, then we can probably use the blit engine.
       */
      if (!(srcX0 - srcX1 == dstX0 - dstX1 &&
            srcY0 - srcY1 == dstY0 - dstY1 &&
            srcX1 >= srcX0 &&
            srcY1 >= srcY0 &&
            srcX0 >= 0 && srcX1 <= readFb->Width &&
            srcY0 >= 0 && srcY1 <= readFb->Height &&
            dstX0 >= 0 && dstX1 <= drawFb->Width &&
            dstY0 >= 0 && dstY1 <= drawFb->Height &&
            !ctx->Scissor.Enabled)) {
         perf_debug("glBlitFramebuffer(): non-1:1 blit.  "
                    "Falling back to software rendering.\n");
         return mask;
      }

      /* Blit to all active draw buffers.  We don't do any pre-checking,
       * because we assume that copying to MRTs is rare, and failure midway
       * through copying is even more rare.  Even if it was to occur, it's
       * safe to let meta start the copy over from scratch, because
       * glBlitFramebuffer completely overwrites the destination pixels, and
       * results are undefined if any destination pixels have a dependency on
       * source pixels.
       */
      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
         struct gl_renderbuffer *dst_rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
         struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb);

         if (!dst_irb) {
            perf_debug("glBlitFramebuffer(): missing dst renderbuffer.  "
                       "Falling back to software rendering.\n");
            return mask;
         }

         gl_format src_format = _mesa_get_srgb_format_linear(src_rb->Format);
         gl_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format);
         if (src_format != dst_format) {
            perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s.  "
                       "Falling back to software rendering.\n",
                       _mesa_get_format_name(src_format),
                       _mesa_get_format_name(dst_format));
            return mask;
         }

         if (!intel_miptree_blit(brw,
                                 src_irb->mt,
                                 src_irb->mt_level, src_irb->mt_layer,
                                 srcX0, srcY0, src_rb->Name == 0,
                                 dst_irb->mt,
                                 dst_irb->mt_level, dst_irb->mt_layer,
                                 dstX0, dstY0, dst_rb->Name == 0,
                                 dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) {
            perf_debug("glBlitFramebuffer(): unknown blit failure.  "
                       "Falling back to software rendering.\n");
            return mask;
         }
      }

      mask &= ~GL_COLOR_BUFFER_BIT;
   }

   return mask;
}
Exemplo n.º 22
0
static bool
do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb,
                      struct gl_renderbuffer *rb, unsigned buf,
                      bool partial_clear, bool encode_srgb, unsigned layer)
{
    struct gl_context *ctx = &brw->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    mesa_format format = irb->mt->format;

    struct brw_blorp_params params;
    brw_blorp_params_init(&params);

    if (!encode_srgb && _mesa_get_format_color_encoding(format) == GL_SRGB)
        format = _mesa_get_srgb_format_linear(format);

    brw_blorp_surface_info_init(brw, &params.dst, irb->mt, irb->mt_level,
                                layer, format, true);

    /* Override the surface format according to the context's sRGB rules. */
    params.dst.brw_surfaceformat = brw->render_target_format[format];

    params.x0 = fb->_Xmin;
    params.x1 = fb->_Xmax;
    if (rb->Name != 0) {
        params.y0 = fb->_Ymin;
        params.y1 = fb->_Ymax;
    } else {
        params.y0 = rb->Height - fb->_Ymax;
        params.y1 = rb->Height - fb->_Ymin;
    }

    memcpy(&params.wm_inputs, ctx->Color.ClearColor.f, sizeof(float) * 4);

    bool use_simd16_replicated_data = true;

    /* From the SNB PRM (Vol4_Part1):
     *
     *     "Replicated data (Message Type = 111) is only supported when
     *      accessing tiled memory.  Using this Message Type to access linear
     *      (untiled) memory is UNDEFINED."
     */
    if (irb->mt->tiling == I915_TILING_NONE)
        use_simd16_replicated_data = false;

    /* Constant color writes ignore everyting in blend and color calculator
     * state.  This is not documented.
     */
    if (set_write_disables(irb, ctx->Color.ColorMask[buf],
                           params.color_write_disable))
        use_simd16_replicated_data = false;

    if (irb->mt->fast_clear_state != INTEL_FAST_CLEAR_STATE_NO_MCS &&
            !partial_clear && use_simd16_replicated_data &&
            brw_is_color_fast_clear_compatible(brw, irb->mt,
                    &ctx->Color.ClearColor)) {
        memset(&params.wm_inputs, 0xff, 4*sizeof(float));
        params.fast_clear_op = GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE;

        brw_get_fast_clear_rect(brw, fb, irb->mt, &params.x0, &params.y0,
                                &params.x1, &params.y1);
    } else {
        brw_meta_get_buffer_rect(fb, &params.x0, &params.y0,
                                 &params.x1, &params.y1);
    }

    brw_blorp_params_get_clear_kernel(brw, &params, use_simd16_replicated_data);

    const bool is_fast_clear =
        params.fast_clear_op == GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE;
    if (is_fast_clear) {
        /* Record the clear color in the miptree so that it will be
         * programmed in SURFACE_STATE by later rendering and resolve
         * operations.
         */
        const bool color_updated = brw_meta_set_fast_clear_color(
                                       brw, irb->mt, &ctx->Color.ClearColor);

        /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the clear
         * is redundant and can be skipped.
         */
        if (!color_updated &&
                irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR)
            return true;

        /* If the MCS buffer hasn't been allocated yet, we need to allocate
         * it now.
         */
        if (!irb->mt->mcs_mt) {
            if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt)) {
                /* MCS allocation failed--probably this will only happen in
                 * out-of-memory conditions.  But in any case, try to recover
                 * by falling back to a non-blorp clear technique.
                 */
                return false;
            }
        }
    }

    const char *clear_type;
    if (is_fast_clear)
        clear_type = "fast";
    else if (use_simd16_replicated_data)
        clear_type = "replicated";
    else
        clear_type = "slow";

    DBG("%s (%s) to mt %p level %d layer %d\n", __FUNCTION__, clear_type,
        irb->mt, irb->mt_level, irb->mt_layer);

    brw_blorp_exec(brw, &params);

    if (is_fast_clear) {
        /* Now that the fast clear has occurred, put the buffer in
         * INTEL_FAST_CLEAR_STATE_CLEAR so that we won't waste time doing
         * redundant clears.
         */
        irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
    } else if (intel_miptree_is_lossless_compressed(brw, irb->mt)) {
        /* Compressed buffers can be cleared also using normal rep-clear. In
         * such case they bahave such as if they were drawn using normal 3D
         * render pipeline, and we simply mark the mcs as dirty.
         */
        assert(partial_clear);
        irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_UNRESOLVED;
    }

    return true;
}
Exemplo n.º 23
0
/*
 * Render a bitmap.
 */
static bool
do_blit_bitmap( struct gl_context *ctx, 
		GLint dstx, GLint dsty,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *irb;
   GLfloat tmpColor[4];
   GLubyte ubcolor[4];
   GLuint color;
   GLsizei bitmap_width = width;
   GLsizei bitmap_height = height;
   GLint px, py;
   GLuint stipple[32];
   GLint orig_dstx = dstx;
   GLint orig_dsty = dsty;

   /* Update draw buffer bounds */
   _mesa_update_state(ctx);

   if (ctx->Depth.Test) {
      /* The blit path produces incorrect results when depth testing is on.
       * It seems the blit Z coord is always 1.0 (the far plane) so fragments
       * will likely be obscured by other, closer geometry.
       */
      return false;
   }

   intel_prepare_render(intel);

   if (fb->_NumColorDrawBuffers != 1) {
      perf_debug("accelerated glBitmap() only supports rendering to a "
                 "single color buffer\n");
      return false;
   }

   irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);

   if (_mesa_is_bufferobj(unpack->BufferObj)) {
      bitmap = map_pbo(ctx, width, height, unpack, bitmap);
      if (bitmap == NULL)
	 return true;	/* even though this is an error, we're done */
   }

   COPY_4V(tmpColor, ctx->Current.RasterColor);

   if (_mesa_need_secondary_color(ctx)) {
       ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
   }

   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);

   switch (irb->mt->format) {
   case MESA_FORMAT_B8G8R8A8_UNORM:
   case MESA_FORMAT_B8G8R8X8_UNORM:
      color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]);
      break;
   case MESA_FORMAT_B5G6R5_UNORM:
      color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]);
      break;
   default:
      perf_debug("Unsupported format %s in accelerated glBitmap()\n",
                 _mesa_get_format_name(irb->mt->format));
      return false;
   }

   if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
      return false;

   /* Clip to buffer bounds and scissor. */
   if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
			     fb->_Xmax, fb->_Ymax,
			     &dstx, &dsty, &width, &height))
      goto out;

   dsty = y_flip(fb, dsty, height);

#define DY 32
#define DX 32

   /* Chop it all into chunks that can be digested by hardware: */
   for (py = 0; py < height; py += DY) {
      for (px = 0; px < width; px += DX) {
	 int h = MIN2(DY, height - py);
	 int w = MIN2(DX, width - px);
	 GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
	 GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
	    ctx->Color.LogicOp : GL_COPY;

	 assert(sz <= sizeof(stipple));
	 memset(stipple, 0, sz);

	 /* May need to adjust this when padding has been introduced in
	  * sz above:
	  *
	  * Have to translate destination coordinates back into source
	  * coordinates.
	  */
         int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack,
                                     bitmap,
                                     -orig_dstx + (dstx + px),
                                     -orig_dsty + y_flip(fb, dsty + py, h),
                                     w, h,
                                     (GLubyte *)stipple,
                                     8,
                                     _mesa_is_winsys_fbo(fb));
         if (count == 0)
	    continue;

	 if (!intelEmitImmediateColorExpandBlit(intel,
						irb->mt->cpp,
						(GLubyte *)stipple,
						sz,
						color,
						irb->mt->region->pitch,
						irb->mt->region->bo,
						0,
						irb->mt->region->tiling,
						dstx + px,
						dsty + py,
						w, h,
						logic_op)) {
	    return false;
	 }

         if (ctx->Query.CurrentOcclusionObject)
            ctx->Query.CurrentOcclusionObject->Result += count;
      }
   }
out:

   if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
      intel_batchbuffer_flush(intel);

   if (_mesa_is_bufferobj(unpack->BufferObj)) {
      /* done with PBO so unmap it now */
      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
   }

   intel_check_front_buffer_rendering(intel);

   return true;
}
Exemplo n.º 24
0
brw_blorp_clear_params::brw_blorp_clear_params(struct brw_context *brw,
                                               struct gl_framebuffer *fb,
                                               struct gl_renderbuffer *rb,
                                               GLubyte *color_mask,
                                               bool partial_clear,
                                               unsigned layer)
{
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);

   dst.set(brw, irb->mt, irb->mt_level, layer, true);

   /* Override the surface format according to the context's sRGB rules. */
   mesa_format format = _mesa_get_render_format(ctx, irb->mt->format);
   dst.brw_surfaceformat = brw->render_target_format[format];

   x0 = fb->_Xmin;
   x1 = fb->_Xmax;
   if (rb->Name != 0) {
      y0 = fb->_Ymin;
      y1 = fb->_Ymax;
   } else {
      y0 = rb->Height - fb->_Ymax;
      y1 = rb->Height - fb->_Ymin;
   }

   float *push_consts = (float *)&wm_push_consts;

   push_consts[0] = ctx->Color.ClearColor.f[0];
   push_consts[1] = ctx->Color.ClearColor.f[1];
   push_consts[2] = ctx->Color.ClearColor.f[2];
   push_consts[3] = ctx->Color.ClearColor.f[3];

   use_wm_prog = true;

   memset(&wm_prog_key, 0, sizeof(wm_prog_key));

   wm_prog_key.use_simd16_replicated_data = true;

   /* From the SNB PRM (Vol4_Part1):
    *
    *     "Replicated data (Message Type = 111) is only supported when
    *      accessing tiled memory.  Using this Message Type to access linear
    *      (untiled) memory is UNDEFINED."
    */
   if (irb->mt->tiling == I915_TILING_NONE)
      wm_prog_key.use_simd16_replicated_data = false;

   /* Constant color writes ignore everyting in blend and color calculator
    * state.  This is not documented.
    */
   for (int i = 0; i < 4; i++) {
      if (_mesa_format_has_color_component(irb->mt->format, i) &&
          !color_mask[i]) {
         color_write_disable[i] = true;
         wm_prog_key.use_simd16_replicated_data = false;
      }
   }

   /* If we can do this as a fast color clear, do so.
    *
    * Note that the condition "!partial_clear" means we only try to do full
    * buffer clears using fast color clear logic.  This is necessary because
    * the fast color clear alignment requirements mean that we typically have
    * to clear a larger rectangle than (x0, y0) to (x1, y1).  Restricting fast
    * color clears to the full-buffer condition guarantees that the extra
    * memory locations that get written to are outside the image boundary (and
    * hence irrelevant).  Note that the rectangle alignment requirements are
    * never larger than the size of a tile, so there is no danger of
    * overflowing beyond the memory belonging to the region.
    */
   if (irb->mt->fast_clear_state != INTEL_FAST_CLEAR_STATE_NO_MCS &&
       !partial_clear && wm_prog_key.use_simd16_replicated_data &&
       is_color_fast_clear_compatible(brw, format, &ctx->Color.ClearColor)) {
      memset(push_consts, 0xff, 4*sizeof(float));
      fast_clear_op = GEN7_FAST_CLEAR_OP_FAST_CLEAR;

      /* Figure out what the clear rectangle needs to be aligned to, and how
       * much it needs to be scaled down.
       */
      unsigned x_align, y_align, x_scaledown, y_scaledown;

      if (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE) {
         /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
          * Target(s)", beneath the "Fast Color Clear" bullet (p327):
          *
          *     Clear pass must have a clear rectangle that must follow
          *     alignment rules in terms of pixels and lines as shown in the
          *     table below. Further, the clear-rectangle height and width
          *     must be multiple of the following dimensions. If the height
          *     and width of the render target being cleared do not meet these
          *     requirements, an MCS buffer can be created such that it
          *     follows the requirement and covers the RT.
          *
          * The alignment size in the table that follows is related to the
          * alignment size returned by intel_get_non_msrt_mcs_alignment(), but
          * with X alignment multiplied by 16 and Y alignment multiplied by 32.
          */
         intel_get_non_msrt_mcs_alignment(brw, irb->mt, &x_align, &y_align);
         x_align *= 16;
         y_align *= 32;

         /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
          * Target(s)", beneath the "Fast Color Clear" bullet (p327):
          *
          *     In order to optimize the performance MCS buffer (when bound to
          *     1X RT) clear similarly to MCS buffer clear for MSRT case,
          *     clear rect is required to be scaled by the following factors
          *     in the horizontal and vertical directions:
          *
          * The X and Y scale down factors in the table that follows are each
          * equal to half the alignment value computed above.
          */
         x_scaledown = x_align / 2;
         y_scaledown = y_align / 2;

         /* From BSpec: 3D-Media-GPGPU Engine > 3D Pipeline > Pixel > Pixel
          * Backend > MCS Buffer for Render Target(s) [DevIVB+] > Table "Color
          * Clear of Non-MultiSampled Render Target Restrictions":
          *
          *   Clear rectangle must be aligned to two times the number of
          *   pixels in the table shown below due to 16x16 hashing across the
          *   slice.
          */
         x_align *= 2;
         y_align *= 2;
      } else {
         /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
          * Target(s)", beneath the "MSAA Compression" bullet (p326):
          *
          *     Clear pass for this case requires that scaled down primitive
          *     is sent down with upper left co-ordinate to coincide with
          *     actual rectangle being cleared. For MSAA, clear rectangle’s
          *     height and width need to as show in the following table in
          *     terms of (width,height) of the RT.
          *
          *     MSAA  Width of Clear Rect  Height of Clear Rect
          *      4X     Ceil(1/8*width)      Ceil(1/2*height)
          *      8X     Ceil(1/2*width)      Ceil(1/2*height)
          *
          * The text "with upper left co-ordinate to coincide with actual
          * rectangle being cleared" is a little confusing--it seems to imply
          * that to clear a rectangle from (x,y) to (x+w,y+h), one needs to
          * feed the pipeline using the rectangle (x,y) to
          * (x+Ceil(w/N),y+Ceil(h/2)), where N is either 2 or 8 depending on
          * the number of samples.  Experiments indicate that this is not
          * quite correct; actually, what the hardware appears to do is to
          * align whatever rectangle is sent down the pipeline to the nearest
          * multiple of 2x2 blocks, and then scale it up by a factor of N
          * horizontally and 2 vertically.  So the resulting alignment is 4
          * vertically and either 4 or 16 horizontally, and the scaledown
          * factor is 2 vertically and either 2 or 8 horizontally.
          */
         switch (irb->mt->num_samples) {
         case 4:
            x_scaledown = 8;
            break;
         case 8:
            x_scaledown = 2;
            break;
         default:
            assert(!"Unexpected sample count for fast clear");
            break;
         }
         y_scaledown = 2;
         x_align = x_scaledown * 2;
         y_align = y_scaledown * 2;
      }

      /* Do the alignment and scaledown. */
      x0 = ROUND_DOWN_TO(x0,  x_align) / x_scaledown;
      y0 = ROUND_DOWN_TO(y0, y_align) / y_scaledown;
      x1 = ALIGN(x1, x_align) / x_scaledown;
      y1 = ALIGN(y1, y_align) / y_scaledown;
   }
}
/**
 * Called by glFramebufferTexture[123]DEXT() (and other places) to
 * prepare for rendering into texture memory.  This might be called
 * many times to choose different texture levels, cube faces, etc
 * before intel_finish_render_texture() is ever called.
 */
static void
intel_render_texture(struct gl_context * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct intel_mipmap_tree *mt = intel_image->mt;
   int layer;

   (void) fb;

   if (att->CubeMapFace > 0) {
      assert(att->Zoffset == 0);
      layer = att->CubeMapFace;
   } else {
      layer = att->Zoffset;
   }

   if (!intel_image->mt) {
      /* Fallback on drawing to a texture that doesn't have a miptree
       * (has a border, width/height 0, etc.)
       */
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      _swrast_render_texture(ctx, fb, att);
      return;
   }
   else if (!irb) {
      intel_miptree_check_level_layer(mt, att->TextureLevel, layer);

      irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0);

      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base);
      }
      else {
         /* fallback to software rendering */
         _swrast_render_texture(ctx, fb, att);
         return;
      }
   }

   if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _swrast_render_texture(ctx, fb, att);
       return;
   }

   irb->tex_image = image;

   DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
       _mesa_get_format_name(image->TexFormat),
       att->Texture->Name, image->Width, image->Height,
       irb->Base.Base.RefCount);

   /* update drawing region, etc */
   intel_draw_buffer(ctx);
}
Exemplo n.º 26
0
bool
do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb,
                      struct gl_renderbuffer *rb, unsigned buf,
                      bool partial_clear, unsigned layer)
{
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);

   brw_blorp_clear_params params(brw, fb, rb, ctx->Color.ColorMask[buf],
                                 partial_clear, layer);

   bool is_fast_clear =
      (params.fast_clear_op == GEN7_FAST_CLEAR_OP_FAST_CLEAR);
   if (is_fast_clear) {
      /* Record the clear color in the miptree so that it will be
       * programmed in SURFACE_STATE by later rendering and resolve
       * operations.
       */
      uint32_t new_color_value =
         compute_fast_clear_color_bits(&ctx->Color.ClearColor);
      if (irb->mt->fast_clear_color_value != new_color_value) {
         irb->mt->fast_clear_color_value = new_color_value;
         brw->state.dirty.brw |= BRW_NEW_SURFACES;
      }

      /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the clear
       * is redundant and can be skipped.
       */
      if (irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR)
         return true;

      /* If the MCS buffer hasn't been allocated yet, we need to allocate
       * it now.
       */
      if (!irb->mt->mcs_mt) {
         if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt)) {
            /* MCS allocation failed--probably this will only happen in
             * out-of-memory conditions.  But in any case, try to recover
             * by falling back to a non-blorp clear technique.
             */
            return false;
         }
         brw->state.dirty.brw |= BRW_NEW_SURFACES;
      }
   }

   const char *clear_type;
   if (is_fast_clear)
      clear_type = "fast";
   else if (params.wm_prog_key.use_simd16_replicated_data)
      clear_type = "replicated";
   else
      clear_type = "slow";

   DBG("%s (%s) to mt %p level %d layer %d\n", __FUNCTION__, clear_type,
       irb->mt, irb->mt_level, irb->mt_layer);

   brw_blorp_exec(brw, &params);

   if (is_fast_clear) {
      /* Now that the fast clear has occurred, put the buffer in
       * INTEL_FAST_CLEAR_STATE_CLEAR so that we won't waste time doing
       * redundant clears.
       */
      irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
   }

   return true;
}
Exemplo n.º 27
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field
 * since that might include software renderbuffers or renderbuffers
 * which we're clearing with triangles.
 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
 */
void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
                        GLint cx, GLint cy, GLint cw, GLint ch)
{
   struct intel_context *intel = intel_context( ctx );
   GLuint clear_depth;
   GLbitfield skipBuffers = 0;
   BATCH_LOCALS;

   if (INTEL_DEBUG & DEBUG_DRI)
      _mesa_printf("%s %x\n", __FUNCTION__, mask);

   /*
    * Compute values for clearing the buffers.
    */
   clear_depth = 0;
   if (mask & BUFFER_BIT_DEPTH) {
      clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear);
   }
   if (mask & BUFFER_BIT_STENCIL) {
      clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
   }

   /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
    * the loop below.
    */
   if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
      skipBuffers = BUFFER_BIT_STENCIL;
   }

   /* XXX Move this flush/lock into the following conditional? */
   intelFlush( &intel->ctx );
   LOCK_HARDWARE( intel );

   if (intel->numClipRects)
   {
      drm_clip_rect_t clear;
      int i;

      if (intel->ctx.DrawBuffer->Name == 0) {
         /* clearing a window */

         /* flip top to bottom */
         clear.x1 = cx + intel->drawX;
         clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
         clear.x2 = clear.x1 + cw;
         clear.y2 = clear.y1 + ch;

         /* adjust for page flipping */
         if ( intel->sarea->pf_current_page == 1 ) {
            const GLuint tmp = mask;
            mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
            if ( tmp & BUFFER_BIT_FRONT_LEFT ) mask |= BUFFER_BIT_BACK_LEFT;
            if ( tmp & BUFFER_BIT_BACK_LEFT )  mask |= BUFFER_BIT_FRONT_LEFT;
         }
      }
      else {
         /* clearing FBO */
         ASSERT(intel->numClipRects == 1);
         ASSERT(intel->pClipRects == &intel->fboRect);
         clear.x1 = cx;
         clear.y1 = intel->ctx.DrawBuffer->Height - cy - ch;
         clear.x2 = clear.y1 + cw;
         clear.y2 = clear.y1 + ch;
         /* no change to mask */
      }

      for (i = 0 ; i < intel->numClipRects ; i++) 
      { 	 
	 const drm_clip_rect_t *box = &intel->pClipRects[i];	 
	 drm_clip_rect_t b;
         GLuint buf;
         GLuint clearMask = mask; /* use copy, since we modify it below */

	 if (!all) {
	    intel_intersect_cliprects(&b, &clear, box);
	 } else {
	    b = *box;
	 }

	 if (0)
	    _mesa_printf("clear %d,%d..%d,%d, mask %x\n", 
			 b.x1, b.y1,
			 b.x2, b.y2, 
			 mask);

         /* Loop over all renderbuffers */
         for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
            const GLbitfield bufBit = 1 << buf;
            if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
               /* OK, clear this renderbuffer */
               const struct intel_renderbuffer *irb
                  = intel_renderbuffer(ctx->DrawBuffer->
                                       Attachment[buf].Renderbuffer);
               GLuint clearVal;
               GLint pitch, cpp;
               GLuint BR13, CMD;

               ASSERT(irb);
               ASSERT(irb->region);

               pitch = irb->region->pitch;
               cpp = irb->region->cpp;

               /* Setup the blit command */
               if (cpp == 4) {
                  BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
                  if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
                     CMD = XY_COLOR_BLT_CMD;
                     if (clearMask & BUFFER_BIT_DEPTH)
                        CMD |= XY_COLOR_BLT_WRITE_RGB;
                     if (clearMask & BUFFER_BIT_STENCIL)
                        CMD |= XY_COLOR_BLT_WRITE_ALPHA;
                  }
                  else {
                     /* clearing RGBA */
                     CMD = (XY_COLOR_BLT_CMD |
                            XY_COLOR_BLT_WRITE_ALPHA | 
                            XY_COLOR_BLT_WRITE_RGB);
                  }
               }
               else {
                  ASSERT(cpp == 2 || cpp == 0);
                  BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
                  CMD = XY_COLOR_BLT_CMD;
               }

               if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
                  clearVal = clear_depth;
               }
               else {
                  clearVal = (cpp == 4)
                     ? intel->ClearColor8888 : intel->ClearColor565;
               }
               /*
               _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
                           buf, irb->Base.Name);
               */
               BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
               OUT_BATCH( CMD );
               OUT_BATCH( BR13 );
               OUT_BATCH( (b.y1 << 16) | b.x1 );
               OUT_BATCH( (b.y2 << 16) | b.x2 );
               OUT_RELOC( irb->region->buffer, DRM_MM_TT|DRM_MM_WRITE,
                          irb->region->draw_offset );
               OUT_BATCH( clearVal );
               ADVANCE_BATCH();
               clearMask &= ~bufBit; /* turn off bit, for faster loop exit */
            }
         }
      }
      intel_batchbuffer_flush( intel->batch );
   }

   UNLOCK_HARDWARE( intel );
}
Exemplo n.º 28
0
/**
 * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc.
 */
static bool
do_blit_copypixels(struct gl_context * ctx,
                   GLint srcx, GLint srcy,
                   GLsizei width, GLsizei height,
                   GLint dstx, GLint dsty, GLenum type)
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct gl_framebuffer *read_fb = ctx->ReadBuffer;
   GLint orig_dstx;
   GLint orig_dsty;
   GLint orig_srcx;
   GLint orig_srcy;
   struct intel_renderbuffer *draw_irb = NULL;
   struct intel_renderbuffer *read_irb = NULL;

   /* Update draw buffer bounds */
   _mesa_update_state(ctx);

   intel_prepare_render(brw);

   switch (type) {
   case GL_COLOR:
      if (fb->_NumColorDrawBuffers != 1) {
	 perf_debug("glCopyPixels() fallback: MRT\n");
	 return false;
      }

      draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
      read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer);
      break;
   case GL_DEPTH_STENCIL_EXT:
      draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
      read_irb =
	 intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer);
      break;
   case GL_DEPTH:
      perf_debug("glCopyPixels() fallback: GL_DEPTH\n");
      return false;
   case GL_STENCIL:
      perf_debug("glCopyPixels() fallback: GL_STENCIL\n");
      return false;
   default:
      perf_debug("glCopyPixels(): Unknown type\n");
      return false;
   }

   if (!draw_irb) {
      perf_debug("glCopyPixels() fallback: missing draw buffer\n");
      return false;
   }

   if (!read_irb) {
      perf_debug("glCopyPixels() fallback: missing read buffer\n");
      return false;
   }

   if (draw_irb->mt->num_samples > 1 || read_irb->mt->num_samples > 1) {
      perf_debug("glCopyPixels() fallback: multisampled buffers\n");
      return false;
   }

   if (ctx->_ImageTransferState) {
      perf_debug("glCopyPixels(): Unsupported image transfer state\n");
      return false;
   }

   if (ctx->Depth.Test) {
      perf_debug("glCopyPixels(): Unsupported depth test state\n");
      return false;
   }

   if (ctx->Stencil._Enabled) {
      perf_debug("glCopyPixels(): Unsupported stencil test state\n");
      return false;
   }

   if (ctx->Fog.Enabled ||
       ctx->Texture._MaxEnabledTexImageUnit != -1 ||
       ctx->FragmentProgram._Enabled) {
      perf_debug("glCopyPixels(): Unsupported fragment shader state\n");
      return false;
   }

   if (ctx->Color.AlphaEnabled ||
       ctx->Color.BlendEnabled) {
      perf_debug("glCopyPixels(): Unsupported blend state\n");
      return false;
   }

   if (!ctx->Color.ColorMask[0][0] ||
       !ctx->Color.ColorMask[0][1] ||
       !ctx->Color.ColorMask[0][2] ||
       !ctx->Color.ColorMask[0][3]) {
      perf_debug("glCopyPixels(): Unsupported color mask state\n");
      return false;
   }

   if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) {
      perf_debug("glCopyPixles(): Unsupported pixel zoom\n");
      return false;
   }

   intel_batchbuffer_flush(brw);

   /* Clip to destination buffer. */
   orig_dstx = dstx;
   orig_dsty = dsty;
   if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
			     fb->_Xmax, fb->_Ymax,
			     &dstx, &dsty, &width, &height))
      goto out;
   /* Adjust src coords for our post-clipped destination origin */
   srcx += dstx - orig_dstx;
   srcy += dsty - orig_dsty;

   /* Clip to source buffer. */
   orig_srcx = srcx;
   orig_srcy = srcy;
   if (!_mesa_clip_to_region(0, 0,
			     read_fb->Width, read_fb->Height,
			     &srcx, &srcy, &width, &height))
      goto out;
   /* Adjust dst coords for our post-clipped source origin */
   dstx += srcx - orig_srcx;
   dsty += srcy - orig_srcy;

   if (!intel_miptree_blit(brw,
                           read_irb->mt, read_irb->mt_level, read_irb->mt_layer,
                           srcx, srcy, _mesa_is_winsys_fbo(read_fb),
                           draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer,
                           dstx, dsty, _mesa_is_winsys_fbo(fb),
                           width, height,
                           (ctx->Color.ColorLogicOpEnabled ?
                            ctx->Color.LogicOp : GL_COPY))) {
      DBG("%s: blit failure\n", __FUNCTION__);
      return false;
   }

   if (ctx->Query.CurrentOcclusionObject)
      ctx->Query.CurrentOcclusionObject->Result += width * height;

out:

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
Exemplo n.º 29
0
bool
brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb,
                    GLbitfield buffers, bool partial_clear)
{
   struct gl_context *ctx = &brw->ctx;
   mesa_format format;
   enum { FAST_CLEAR, REP_CLEAR, PLAIN_CLEAR } clear_type;
   GLbitfield plain_clear_buffers, meta_save, rep_clear_buffers, fast_clear_buffers;
   struct rect fast_clear_rect, clear_rect;
   int layers;

   fast_clear_buffers = rep_clear_buffers = plain_clear_buffers = 0;

   /* First we loop through the color draw buffers and determine which ones
    * can be fast cleared, which ones can use the replicated write and which
    * ones have to fall back to regular color clear.
    */
   for (unsigned buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
      struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
      struct intel_renderbuffer *irb = intel_renderbuffer(rb);
      int index = fb->_ColorDrawBufferIndexes[buf];

      /* Only clear the buffers present in the provided mask */
      if (((1 << index) & buffers) == 0)
         continue;

      /* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
       * the framebuffer can be complete with some attachments missing.  In
       * this case the _ColorDrawBuffers pointer will be NULL.
       */
      if (rb == NULL)
         continue;

      clear_type = FAST_CLEAR;

      /* We don't have fast clear until gen7. */
      if (brw->gen < 7)
         clear_type = REP_CLEAR;

      if (irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_NO_MCS)
         clear_type = REP_CLEAR;

      /* We can't do scissored fast clears because of the restrictions on the
       * fast clear rectangle size.
       */
      if (partial_clear)
         clear_type = REP_CLEAR;

      /* Fast clear is only supported for colors where all components are
       * either 0 or 1.
       */
      format = _mesa_get_render_format(ctx, irb->mt->format);
      if (!is_color_fast_clear_compatible(brw, format, &ctx->Color.ClearColor))
         clear_type = REP_CLEAR;

      /* From the SNB PRM (Vol4_Part1):
       *
       *     "Replicated data (Message Type = 111) is only supported when
       *      accessing tiled memory.  Using this Message Type to access
       *      linear (untiled) memory is UNDEFINED."
       */
      if (irb->mt->tiling == I915_TILING_NONE) {
         perf_debug("falling back to plain clear because buffers are untiled\n");
         clear_type = PLAIN_CLEAR;
      }

      /* Constant color writes ignore everything in blend and color calculator
       * state.  This is not documented.
       */
      GLubyte *color_mask = ctx->Color.ColorMask[buf];
      for (int i = 0; i < 4; i++) {
         if (_mesa_format_has_color_component(irb->mt->format, i) &&
             !color_mask[i]) {
            perf_debug("falling back to plain clear because of color mask\n");
            clear_type = PLAIN_CLEAR;
         }
      }

      /* Allocate the MCS for non MSRT surfaces now if we're doing a fast
       * clear and we don't have the MCS yet.  On failure, fall back to
       * replicated clear.
       */
      if (clear_type == FAST_CLEAR && irb->mt->mcs_mt == NULL)
         if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt))
            clear_type = REP_CLEAR;

      switch (clear_type) {
      case FAST_CLEAR:
         irb->mt->fast_clear_color_value =
            compute_fast_clear_color_bits(&ctx->Color.ClearColor);
         irb->need_downsample = true;

         /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the
          * clear is redundant and can be skipped.  Only skip after we've
          * updated the fast clear color above though.
          */
         if (irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR)
            continue;

         /* Set fast_clear_state to RESOLVED so we don't try resolve them when
          * we draw, in case the mt is also bound as a texture.
          */
         irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
         irb->need_downsample = true;
         fast_clear_buffers |= 1 << index;
         get_fast_clear_rect(brw, fb, irb, &fast_clear_rect);
         break;

      case REP_CLEAR:
         rep_clear_buffers |= 1 << index;
         get_buffer_rect(brw, fb, irb, &clear_rect);
         break;

      case PLAIN_CLEAR:
         plain_clear_buffers |= 1 << index;
         get_buffer_rect(brw, fb, irb, &clear_rect);
         continue;
      }
   }

   if (!(fast_clear_buffers | rep_clear_buffers)) {
      if (plain_clear_buffers)
         /* If we only have plain clears, skip the meta save/restore. */
         goto out;
      else
         /* Nothing left to do.  This happens when we hit the redundant fast
          * clear case above and nothing else.
          */
         return true;
   }

   meta_save =
      MESA_META_ALPHA_TEST |
      MESA_META_BLEND |
      MESA_META_DEPTH_TEST |
      MESA_META_RASTERIZATION |
      MESA_META_SHADER |
      MESA_META_STENCIL_TEST |
      MESA_META_VERTEX |
      MESA_META_VIEWPORT |
      MESA_META_CLIP |
      MESA_META_CLAMP_FRAGMENT_COLOR |
      MESA_META_MULTISAMPLE |
      MESA_META_OCCLUSION_QUERY |
      MESA_META_DRAW_BUFFERS;

   _mesa_meta_begin(ctx, meta_save);

   if (!brw_fast_clear_init(brw)) {
      /* This is going to be hard to recover from, most likely out of memory.
       * Bail and let meta try and (probably) fail for us.
       */
      plain_clear_buffers = buffers;
      goto bail_to_meta;
   }

   /* Clears never have the color clamped. */
   if (ctx->Extensions.ARB_color_buffer_float)
      _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);

   _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
   _mesa_DepthMask(GL_FALSE);
   _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);

   use_rectlist(brw, true);

   layers = MAX2(1, fb->MaxNumLayers);
   if (fast_clear_buffers) {
      _mesa_meta_drawbuffers_from_bitfield(fast_clear_buffers);
      brw_bind_rep_write_shader(brw, (float *) fast_clear_color);
      set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE);
      brw_draw_rectlist(ctx, &fast_clear_rect, layers);
      set_fast_clear_op(brw, 0);
   }

   if (rep_clear_buffers) {
      _mesa_meta_drawbuffers_from_bitfield(rep_clear_buffers);
      brw_bind_rep_write_shader(brw, ctx->Color.ClearColor.f);
      brw_draw_rectlist(ctx, &clear_rect, layers);
   }

   /* Now set the mts we cleared to INTEL_FAST_CLEAR_STATE_CLEAR so we'll
    * resolve them eventually.
    */
   for (unsigned buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
      struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
      struct intel_renderbuffer *irb = intel_renderbuffer(rb);
      int index = fb->_ColorDrawBufferIndexes[buf];

      if ((1 << index) & fast_clear_buffers)
         irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
   }

 bail_to_meta:
   /* Dirty _NEW_BUFFERS so we reemit SURFACE_STATE which sets the fast clear
    * color before resolve and sets irb->mt->fast_clear_state to UNRESOLVED if
    * we render to it.
    */
   brw->NewGLState |= _NEW_BUFFERS;


   /* Set the custom state back to normal and dirty the same bits as above */
   use_rectlist(brw, false);

   _mesa_meta_end(ctx);

   /* From BSpec: Render Target Fast Clear:
    *
    *     After Render target fast clear, pipe-control with color cache
    *     write-flush must be issued before sending any DRAW commands on that
    *     render target.
    */
   intel_batchbuffer_emit_mi_flush(brw);

   /* If we had to fall back to plain clear for any buffers, clear those now
    * by calling into meta.
    */
 out:
   if (plain_clear_buffers)
      _mesa_meta_glsl_Clear(&brw->ctx, plain_clear_buffers);

   return true;
}
Exemplo n.º 30
0
/**
 * Map or unmap all the renderbuffers which we may need during
 * software rendering.
 * XXX in the future, we could probably convey extra information to
 * reduce the number of mappings needed.  I.e. if doing a glReadPixels
 * from the depth buffer, we really only need one mapping.
 *
 * XXX Rewrite this function someday.
 * We can probably just loop over all the renderbuffer attachments,
 * map/unmap all of them, and not worry about the _ColorDrawBuffers
 * _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
 */
static void
intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
{
   GLcontext *ctx = &intel->ctx;
   GLuint i, j;
   struct intel_renderbuffer *irb;

   /* color draw buffers */
   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
      for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) {
         struct gl_renderbuffer *rb =
            ctx->DrawBuffer->_ColorDrawBuffers[i][j];
         irb = intel_renderbuffer(rb);
         if (irb) {
            /* this is a user-created intel_renderbuffer */
            if (irb->region) {
               if (map)
                  intel_region_map(intel->intelScreen, irb->region);
               else
                  intel_region_unmap(intel->intelScreen, irb->region);
            }
            irb->pfMap = irb->region->map;
            irb->pfPitch = irb->region->pitch;
         }
      }
   }

   /* check for render to textures */
   for (i = 0; i < BUFFER_COUNT; i++) {
      struct gl_renderbuffer_attachment *att =
         ctx->DrawBuffer->Attachment + i;
      struct gl_texture_object *tex = att->Texture;
      if (tex) {
         /* render to texture */
         ASSERT(att->Renderbuffer);
         if (map) {
            struct gl_texture_image *texImg;
            texImg = tex->Image[att->CubeMapFace][att->TextureLevel];
            intel_tex_map_images(intel, intel_texture_object(tex));
         }
         else {
            intel_tex_unmap_images(intel, intel_texture_object(tex));
         }
      }
   }

   /* color read buffers */
   irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
   if (irb && irb->region) {
      if (map)
         intel_region_map(intel->intelScreen, irb->region);
      else
         intel_region_unmap(intel->intelScreen, irb->region);
      irb->pfMap = irb->region->map;
      irb->pfPitch = irb->region->pitch;
   }

   /* Account for front/back color page flipping.
    * The span routines use the pfMap and pfPitch fields which will
    * swap the front/back region map/pitch if we're page flipped.
    * Do this after mapping, above, so the map field is valid.
    */
#if 0
   if (map && ctx->DrawBuffer->Name == 0) {
      struct intel_renderbuffer *irbFront
         = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_FRONT_LEFT);
      struct intel_renderbuffer *irbBack
         = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_BACK_LEFT);
      if (irbBack) {
         /* double buffered */
         if (intel->sarea->pf_current_page == 0) {
            irbFront->pfMap = irbFront->region->map;
            irbFront->pfPitch = irbFront->region->pitch;
            irbBack->pfMap = irbBack->region->map;
            irbBack->pfPitch = irbBack->region->pitch;
         }
         else {
            irbFront->pfMap = irbBack->region->map;
            irbFront->pfPitch = irbBack->region->pitch;
            irbBack->pfMap = irbFront->region->map;
            irbBack->pfPitch = irbFront->region->pitch;
         }
      }
   }
#endif

   /* depth buffer (Note wrapper!) */
   if (ctx->DrawBuffer->_DepthBuffer) {
      irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped);
      if (irb && irb->region && irb->Base.Name != 0) {
         if (map) {
            intel_region_map(intel->intelScreen, irb->region);
            irb->pfMap = irb->region->map;
            irb->pfPitch = irb->region->pitch;
         }
         else {
            intel_region_unmap(intel->intelScreen, irb->region);
            irb->pfMap = NULL;
            irb->pfPitch = 0;
         }
      }
   }

   /* stencil buffer (Note wrapper!) */
   if (ctx->DrawBuffer->_StencilBuffer) {
      irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped);
      if (irb && irb->region && irb->Base.Name != 0) {
         if (map) {
            intel_region_map(intel->intelScreen, irb->region);
            irb->pfMap = irb->region->map;
            irb->pfPitch = irb->region->pitch;
         }
         else {
            intel_region_unmap(intel->intelScreen, irb->region);
            irb->pfMap = NULL;
            irb->pfPitch = 0;
         }
      }
   }
}