+static void
+radeon_map_renderbuffer_z16(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint x, GLuint y, GLuint w, GLuint h,
+ GLbitfield mode,
+ GLubyte **out_map,
+ GLint *out_stride)
+{
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+ uint16_t *untiled_z16_map, *tiled_z16_map;
+ int ret;
+ int y_flip = (rb->Name == 0) ? -1 : 1;
+ int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
+ uint32_t pitch = w * rrb->cpp;
+
+ rrb->map_pitch = pitch;
+
+ rrb->map_buffer = malloc(w * h * 2);
+ ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
+ assert(!ret);
+ (void) ret;
+
+ untiled_z16_map = rrb->map_buffer;
+ tiled_z16_map = rrb->bo->ptr;
+
+ for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) {
+ for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
+ uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias;
+ uint32_t src_offset = get_depth_z16(rrb, x + pix_x, flipped_y);
+ uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
+ untiled_z16_map[dst_offset/2] = tiled_z16_map[src_offset/2];
+ }
+ }
+
+ radeon_bo_unmap(rrb->bo);
+
+ *out_map = rrb->map_buffer;
+ *out_stride = rrb->map_pitch;
+}
+
+static void
+radeon_map_renderbuffer(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint x, GLuint y, GLuint w, GLuint h,
+ GLbitfield mode,
+ GLubyte **out_map,
+ GLint *out_stride)
+{
+ struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+ GLubyte *map;
+ GLboolean ok;
+ int stride, flip_stride;
+ int ret;
+ int src_x, src_y;
+
+ if (!rrb || !rrb->bo) {
+ *out_map = NULL;
+ *out_stride = 0;
+ return;
+ }
+
+ rrb->map_mode = mode;
+ rrb->map_x = x;
+ rrb->map_y = y;
+ rrb->map_w = w;
+ rrb->map_h = h;
+ rrb->map_pitch = rrb->pitch;
+
+ ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp);
+ if (ok) {
+ if (rb->Name) {
+ src_x = x;
+ src_y = y;
+ } else {
+ src_x = x;
+ src_y = rrb->base.Base.Height - y - h;
+ }
+
+ /* Make a temporary buffer and blit the current contents of the renderbuffer
+ * out to it. This gives us linear access to the buffer, instead of having
+ * to do detiling in software.
+ */
+
+ rrb->map_pitch = rrb->pitch;
+
+ assert(!rrb->map_bo);
+ rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
+ rrb->map_pitch * h, 4,
+ RADEON_GEM_DOMAIN_GTT, 0);
+
+ ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
+ rb->Format, rrb->pitch / rrb->cpp,
+ rb->Width, rb->Height,
+ src_x, src_y,
+ rrb->map_bo, 0,
+ rb->Format, rrb->map_pitch / rrb->cpp,
+ w, h,
+ 0, 0,
+ w, h,
+ GL_FALSE);
+ assert(ok);
+
+ ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
+ assert(!ret);
+
+ map = rrb->map_bo->ptr;
+
+ if (rb->Name) {
+ *out_map = map;
+ *out_stride = rrb->map_pitch;
+ } else {
+ *out_map = map + (h - 1) * rrb->map_pitch;
+ *out_stride = -rrb->map_pitch;
+ }
+ return;
+ }
+
+ /* sw fallback flush stuff */
+ if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) {
+ radeon_firevertices(rmesa);
+ }
+
+ if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
+ if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) {
+ radeon_map_renderbuffer_s8z24(ctx, rb, x, y, w, h,
+ mode, out_map, out_stride);
+ return;
+ }
+ if (rb->Format == MESA_FORMAT_Z_UNORM16) {
+ radeon_map_renderbuffer_z16(ctx, rb, x, y, w, h,
+ mode, out_map, out_stride);
+ return;
+ }
+ }
+
+ ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
+ assert(!ret);
+ (void) ret;
+
+ map = rrb->bo->ptr;
+ stride = rrb->map_pitch;
+
+ if (rb->Name == 0) {
+ y = rb->Height - 1 - y;
+ flip_stride = -stride;
+ } else {
+ flip_stride = stride;
+ map += rrb->draw_offset;
+ }
+
+ map += x * rrb->cpp;
+ map += (int)y * stride;
+
+ *out_map = map;
+ *out_stride = flip_stride;
+}
+
+static void
+radeon_unmap_renderbuffer_s8z24(struct gl_context *ctx,
+ struct gl_renderbuffer *rb)
+{
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+
+ if (!rrb->map_buffer)
+ return;
+
+ if (rrb->map_mode & GL_MAP_WRITE_BIT) {
+ uint32_t *untiled_s8z24_map = rrb->map_buffer;
+ uint32_t *tiled_s8z24_map;
+ int y_flip = (rb->Name == 0) ? -1 : 1;
+ int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
+
+ radeon_bo_map(rrb->bo, 1);
+
+ tiled_s8z24_map = rrb->bo->ptr;
+
+ for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
+ for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
+ uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
+ uint32_t dst_offset = get_depth_z32(rrb, rrb->map_x + pix_x, flipped_y);
+ uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
+ tiled_s8z24_map[dst_offset/4] = untiled_s8z24_map[src_offset/4];
+ }
+ }
+ radeon_bo_unmap(rrb->bo);
+ }
+ free(rrb->map_buffer);
+ rrb->map_buffer = NULL;
+}
+
+static void
+radeon_unmap_renderbuffer_z16(struct gl_context *ctx,
+ struct gl_renderbuffer *rb)
+{
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+
+ if (!rrb->map_buffer)
+ return;
+
+ if (rrb->map_mode & GL_MAP_WRITE_BIT) {
+ uint16_t *untiled_z16_map = rrb->map_buffer;
+ uint16_t *tiled_z16_map;
+ int y_flip = (rb->Name == 0) ? -1 : 1;
+ int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
+
+ radeon_bo_map(rrb->bo, 1);
+
+ tiled_z16_map = rrb->bo->ptr;
+
+ for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
+ for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
+ uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
+ uint32_t dst_offset = get_depth_z16(rrb, rrb->map_x + pix_x, flipped_y);
+ uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
+ tiled_z16_map[dst_offset/2] = untiled_z16_map[src_offset/2];
+ }
+ }
+ radeon_bo_unmap(rrb->bo);
+ }
+ free(rrb->map_buffer);
+ rrb->map_buffer = NULL;
+}
+
+
+static void
+radeon_unmap_renderbuffer(struct gl_context *ctx,
+ struct gl_renderbuffer *rb)
+{
+ struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+
+ if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
+ if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) {
+ radeon_unmap_renderbuffer_s8z24(ctx, rb);
+ return;
+ }
+ if (rb->Format == MESA_FORMAT_Z_UNORM16) {
+ radeon_unmap_renderbuffer_z16(ctx, rb);
+ return;
+ }
+ }
+
+ if (!rrb->map_bo) {
+ if (rrb->bo)
+ radeon_bo_unmap(rrb->bo);
+ return;
+ }
+
+ radeon_bo_unmap(rrb->map_bo);
+
+ if (rrb->map_mode & GL_MAP_WRITE_BIT) {
+ GLboolean ok;
+ ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
+ rb->Format, rrb->map_pitch / rrb->cpp,
+ rrb->map_w, rrb->map_h,
+ 0, 0,
+ rrb->bo, rrb->draw_offset,
+ rb->Format, rrb->pitch / rrb->cpp,
+ rb->Width, rb->Height,
+ rrb->map_x, rrb->map_y,
+ rrb->map_w, rrb->map_h,
+ GL_FALSE);
+ assert(ok);
+ (void) ok;
+ }
+
+ radeon_bo_unref(rrb->map_bo);
+ rrb->map_bo = NULL;
+}
+
+