Ejemplo n.º 1
0
/* XXX: Do this for TexSubImage also:
 */
static GLboolean
try_pbo_upload(struct intel_context *intel,
               struct intel_texture_image *intelImage,
               const struct gl_pixelstore_attrib *unpack,
               GLint internalFormat,
               GLint width, GLint height,
               GLenum format, GLenum type, const void *pixels)
{
   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset, src_stride;
   GLuint dst_offset, dst_stride;

   if (!pbo ||
       intel->ctx._ImageTransferState ||
       unpack->SkipPixels || unpack->SkipRows) {
      _mesa_printf("%s: failure 1\n", __FUNCTION__);
      return GL_FALSE;
   }

   src_offset = (GLuint) pixels;

   if (unpack->RowLength > 0)
      src_stride = unpack->RowLength;
   else
      src_stride = width;

   dst_offset = intel_miptree_image_offset(intelImage->mt,
                                           intelImage->face,
                                           intelImage->level);

   dst_stride = intelImage->mt->pitch;

   intelFlush(&intel->ctx);
   LOCK_HARDWARE(intel);
   {
      struct _DriBufferObject *src_buffer =
         intel_bufferobj_buffer(intel, pbo, INTEL_READ);
      struct _DriBufferObject *dst_buffer =
         intel_region_buffer(intel->intelScreen, intelImage->mt->region,
                             INTEL_WRITE_FULL);


      intelEmitCopyBlit(intel,
                        intelImage->mt->cpp,
                        src_stride, src_buffer, src_offset,
                        dst_stride, dst_buffer, dst_offset,
                        0, 0, 0, 0, width, height,
			GL_COPY);

      intel_batchbuffer_flush(intel->batch);
   }
   UNLOCK_HARDWARE(intel);

   return GL_TRUE;
}
/**
 * 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)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint clear_depth;
   GLbitfield skipBuffers = 0;
   BATCH_LOCALS;

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

   /*
    * Compute values for clearing the buffers.
    */
   clear_depth = 0;
   if (mask & BUFFER_BIT_DEPTH) {
      clear_depth = (GLuint) (fb->_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) {
      GLint cx, cy, cw, ch;
      drm_clip_rect_t clear;
      int i;

      /* Get clear bounds after locking */
      cx = fb->_Xmin;
      cy = fb->_Ymin;
      cw = fb->_Xmax - cx;
      ch = fb->_Ymax - cy;

      if (fb->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;
      }
      else {
         /* clearing FBO */
         assert(intel->numClipRects == 1);
         assert(intel->pClipRects == &intel->fboRect);
         clear.x1 = cx;
         clear.y1 = cy;
         clear.x2 = clear.x1 + 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 */
         GLboolean all = (cw == fb->Width && ch == fb->Height);

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

         if (b.x1 >= b.x2 || b.y1 >= b.y2)
            continue;

         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 */
               struct intel_region *irb_region =
		  intel_get_rb_region(fb, buf);
               dri_bo *write_buffer =
                  intel_region_buffer(intel->intelScreen, irb_region,
                                      all ? INTEL_WRITE_FULL :
                                      INTEL_WRITE_PART);

               GLuint clearVal;
               GLint pitch, cpp;
               GLuint BR13, CMD;

               ASSERT(irb_region);

               pitch = irb_region->pitch;
               cpp = irb_region->cpp;

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

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

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

#ifndef I915
	       if (irb_region->tiled) {
		  CMD |= XY_DST_TILED;
		  pitch /= 4;
	       }
#endif
	       BR13 |= (pitch * cpp);

               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);
                */
	       intel_wait_flips(intel, INTEL_BATCH_NO_CLIPRECTS);

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

               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(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_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);
}
Ejemplo n.º 3
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;
}