/* 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); }
/** * 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; }