Ejemplo n.º 1
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes 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
 */
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint clear_depth_value, clear_depth_mask;
   GLint cx, cy, cw, ch;
   GLbitfield fail_mask = 0;
   BATCH_LOCALS;

   /* Note: we don't use this function on Gen7+ hardware, so we can safely
    * ignore fast color clear issues.
    */
   assert(intel->gen < 7);

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

   cx = fb->_Xmin;
   if (_mesa_is_winsys_fbo(fb))
      cy = ctx->DrawBuffer->Height - fb->_Ymax;
   else
      cy = fb->_Ymin;
   cw = fb->_Xmax - fb->_Xmin;
   ch = fb->_Ymax - fb->_Ymin;

   if (cw == 0 || ch == 0)
      return 0;

   /* Loop over all renderbuffers */
   mask &= (1 << BUFFER_COUNT) - 1;
   while (mask) {
      GLuint buf = ffs(mask) - 1;
      bool is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
      struct intel_renderbuffer *irb;
      int x1, y1, x2, y2;
      uint32_t clear_val;
      uint32_t BR13, CMD;
      struct intel_region *region;
      int pitch, cpp;
      drm_intel_bo *aper_array[2];

      mask &= ~(1 << buf);

      irb = intel_get_renderbuffer(fb, buf);
      if (irb && irb->mt) {
	 region = irb->mt->region;
	 assert(region);
	 assert(region->bo);
      } else {
         fail_mask |= 1 << buf;
         continue;
      }

      /* OK, clear this renderbuffer */
      x1 = cx + irb->draw_x;
      y1 = cy + irb->draw_y;
      x2 = cx + cw + irb->draw_x;
      y2 = cy + ch + irb->draw_y;

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

      DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
	  __FUNCTION__,
	  region->bo, pitch,
	  x1, y1, x2 - x1, y2 - y1);

      BR13 = 0xf0 << 16;
      CMD = XY_COLOR_BLT_CMD;

      /* Setup the blit command */
      if (cpp == 4) {
	 if (is_depth_stencil) {
	    CMD |= clear_depth_mask;
	 } else {
	    /* clearing RGBA */
	    CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
	 }
      }

      assert(region->tiling != I915_TILING_Y);

      BR13 |= pitch;

      if (is_depth_stencil) {
	 clear_val = clear_depth_value;
      } else {
	 uint8_t clear[4];
	 GLfloat *color = ctx->Color.ClearColor.f;

	 _mesa_unclamped_float_rgba_to_ubyte(clear, color);

	 switch (intel_rb_format(irb)) {
	 case MESA_FORMAT_ARGB8888:
	 case MESA_FORMAT_XRGB8888:
	    clear_val = PACK_COLOR_8888(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_RGB565:
	    clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_ARGB4444:
	    clear_val = PACK_COLOR_4444(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_ARGB1555:
	    clear_val = PACK_COLOR_1555(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_A8:
	    clear_val = PACK_COLOR_8888(clear[3], clear[3],
					clear[3], clear[3]);
	    break;
	 default:
	    fail_mask |= 1 << buf;
	    continue;
	 }
      }

      BR13 |= br13_for_cpp(cpp);

      assert(x1 < x2);
      assert(y1 < y2);

      /* do space check before going any further */
      aper_array[0] = intel->batch.bo;
      aper_array[1] = region->bo;

      if (drm_intel_bufmgr_check_aperture_space(aper_array,
						ARRAY_SIZE(aper_array)) != 0) {
	 intel_batchbuffer_flush(intel);
      }

      BEGIN_BATCH(6);
      OUT_BATCH(CMD | (6 - 2));
      OUT_BATCH(BR13);
      OUT_BATCH((y1 << 16) | x1);
      OUT_BATCH((y2 << 16) | x2);
      OUT_RELOC_FENCED(region->bo,
		       I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
		       0);
      OUT_BATCH(clear_val);
      ADVANCE_BATCH();

      if (intel->always_flush_cache)
	 intel_batchbuffer_emit_mi_flush(intel);

      if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
	 mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
   }

   return fail_mask;
}
Ejemplo n.º 2
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes 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
 */
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
    struct intel_context *intel = intel_context(ctx);
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    GLuint clear_depth_value, clear_depth_mask;
    GLboolean all;
    GLint cx, cy, cw, ch;
    GLbitfield fail_mask = 0;
    BATCH_LOCALS;

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

    cx = fb->_Xmin;
    if (fb->Name == 0)
        cy = ctx->DrawBuffer->Height - fb->_Ymax;
    else
        cy = fb->_Ymin;
    cw = fb->_Xmax - fb->_Xmin;
    ch = fb->_Ymax - fb->_Ymin;

    if (cw == 0 || ch == 0)
        return 0;

    all = (cw == fb->Width && ch == fb->Height);

    /* Loop over all renderbuffers */
    mask &= (1 << BUFFER_COUNT) - 1;
    while (mask) {
        GLuint buf = _mesa_ffs(mask) - 1;
        GLboolean is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
        struct intel_renderbuffer *irb;
        drm_intel_bo *write_buffer;
        int x1, y1, x2, y2;
        uint32_t clear_val;
        uint32_t BR13, CMD;
        int pitch, cpp;
        drm_intel_bo *aper_array[2];

        mask &= ~(1 << buf);

        irb = intel_get_renderbuffer(fb, buf);
        if (irb == NULL || irb->region == NULL || irb->region->buffer == NULL) {
            fail_mask |= 1 << buf;
            continue;
        }

        /* OK, clear this renderbuffer */
        write_buffer = intel_region_buffer(intel, irb->region,
                                           all ? INTEL_WRITE_FULL :
                                           INTEL_WRITE_PART);
        x1 = cx + irb->draw_x;
        y1 = cy + irb->draw_y;
        x2 = cx + cw + irb->draw_x;
        y2 = cy + ch + irb->draw_y;

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

        DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
            __FUNCTION__,
            irb->region->buffer, (pitch * cpp),
            x1, y1, x2 - x1, y2 - y1);

        BR13 = 0xf0 << 16;
        CMD = XY_COLOR_BLT_CMD;

        /* Setup the blit command */
        if (cpp == 4) {
            if (is_depth_stencil) {
                CMD |= clear_depth_mask;
            } else {
                /* clearing RGBA */
                CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
            }
        }

        assert(irb->region->tiling != I915_TILING_Y);

#ifndef I915
        if (irb->region->tiling != I915_TILING_NONE) {
            CMD |= XY_DST_TILED;
            pitch /= 4;
        }
#endif
        BR13 |= (pitch * cpp);

        if (is_depth_stencil) {
            clear_val = clear_depth_value;
        } else {
            uint8_t clear[4];
            GLclampf *color = ctx->Color.ClearColor;

            CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
            CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
            CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
            CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);

            switch (irb->Base.Format) {
            case MESA_FORMAT_ARGB8888:
            case MESA_FORMAT_XRGB8888:
                clear_val = PACK_COLOR_8888(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_RGB565:
                clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
                break;
            case MESA_FORMAT_ARGB4444:
                clear_val = PACK_COLOR_4444(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_ARGB1555:
                clear_val = PACK_COLOR_1555(clear[3], clear[0],
                                            clear[1], clear[2]);
                break;
            case MESA_FORMAT_A8:
                clear_val = PACK_COLOR_8888(clear[3], clear[3],
                                            clear[3], clear[3]);
                break;
            default:
                fail_mask |= 1 << buf;
                continue;
            }
        }

        BR13 |= br13_for_cpp(cpp);

        assert(x1 < x2);
        assert(y1 < y2);

        /* do space check before going any further */
        aper_array[0] = intel->batch.bo;
        aper_array[1] = write_buffer;

        if (drm_intel_bufmgr_check_aperture_space(aper_array,
                ARRAY_SIZE(aper_array)) != 0) {
            intel_batchbuffer_flush(intel);
        }

        BEGIN_BATCH_BLT(6);
        OUT_BATCH(CMD);
        OUT_BATCH(BR13);
        OUT_BATCH((y1 << 16) | x1);
        OUT_BATCH((y2 << 16) | x2);
        OUT_RELOC_FENCED(write_buffer,
                         I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                         0);
        OUT_BATCH(clear_val);
        ADVANCE_BATCH();

        if (intel->always_flush_cache)
            intel_batchbuffer_emit_mi_flush(intel);

        if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
            mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
    }

    return fail_mask;
}