static void radeon_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *texImage, GLuint slice) { radeon_texture_image *image = get_radeon_texture_image(texImage); if (image->bo) radeon_bo_unmap(image->bo); else if (image->mt) radeon_bo_unmap(image->mt->bo); }
compute_shader::compute_shader(r800_state* state, std::string fname) { FILE *f = fopen(fname.c_str(), "r"); assert(f); fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); char* buf = new char[size]; fread(buf, 1, size, f); fclose(f); lds_alloc = 0; num_gprs = 10; temp_gprs = 0; global_gprs = 0; stack_size = 16; thread_num = 4; //TODO: how to configure it? dyn_gpr_limit = 0; alloc_size = size; binary_code_bo = state->bo_open(0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); assert(binary_code_bo != NULL); assert(radeon_bo_map(binary_code_bo, 1) == 0); memcpy(binary_code_bo->ptr, buf, size); radeon_bo_unmap(binary_code_bo); }
static cairo_surface_t * radeon_surface_map_to_image (radeon_surface_t *surface) { if (surface->base.fallback == NULL) { cairo_surface_t *image; cairo_status_t status; void *ptr; if (surface->base.base.backend->flush != NULL) { status = surface->base.base.backend->flush (surface); if (unlikely (status)) return _cairo_surface_create_in_error (status); } ptr = radeon_bo_map (to_radeon_device (surface->base.base.device), to_radeon_bo (surface->base.bo)); if (unlikely (ptr == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); image = cairo_image_surface_create_for_data (ptr, surface->base.format, surface->base.width, surface->base.height, surface->base.stride); if (unlikely (image->status)) { radeon_bo_unmap (to_radeon_bo (surface->base.bo)); return image; } surface->base.fallback = image; } return surface->base.fallback; }
static void r700SendQueryBegin(GLcontext *ctx, struct radeon_state_atom *atom) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); struct radeon_query_object *query = radeon->query.current; BATCH_LOCALS(radeon); radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__); /* clear the buffer */ radeon_bo_map(query->bo, GL_FALSE); memset(query->bo->ptr, 0, 4 * 2 * sizeof(uint64_t)); /* 4 DBs, 2 qwords each */ radeon_bo_unmap(query->bo); radeon_cs_space_check_with_bo(radeon->cmdbuf.cs, query->bo, 0, RADEON_GEM_DOMAIN_GTT); BEGIN_BATCH_NO_AUTOSTATE(4 + 2); R600_OUT_BATCH(CP_PACKET3(R600_IT_EVENT_WRITE, 2)); R600_OUT_BATCH(ZPASS_DONE); R600_OUT_BATCH(query->curr_offset); /* hw writes qwords */ R600_OUT_BATCH(0x00000000); R600_OUT_BATCH_RELOC(VGT_EVENT_INITIATOR, query->bo, 0, 0, RADEON_GEM_DOMAIN_GTT, 0); END_BATCH(); query->emitted_begin = GL_TRUE; }
void r200FlushElts(struct gl_context *ctx) { r200ContextPtr rmesa = R200_CONTEXT(ctx); int nr, elt_used = rmesa->tcl.elt_used; radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used); assert( rmesa->radeon.dma.flush == r200FlushElts ); rmesa->radeon.dma.flush = NULL; nr = elt_used / 2; radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo); r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive); radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo); rmesa->radeon.tcl.elt_dma_bo = NULL; if (R200_ELT_BUF_SZ > elt_used) radeonReturnDmaRegion(&rmesa->radeon, R200_ELT_BUF_SZ - elt_used); if (radeon_is_debug_enabled(RADEON_SYNC, RADEON_CRITICAL) && !rmesa->radeon.radeonScreen->kernel_mm) { radeon_print(RADEON_SYNC, RADEON_NORMAL, "%s: Syncing\n", __FUNCTION__); radeonFinish( rmesa->radeon.glCtx ); } }
/** * Ensure that the given image is stored in the given miptree from now on. */ static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_texture_image *image, int face, int level) { radeon_mipmap_level *dstlvl = &mt->levels[level]; unsigned char *dest; assert(image->mt != mt); assert(dstlvl->valid); assert(dstlvl->width == image->base.Base.Width); assert(dstlvl->height == image->base.Base.Height); assert(dstlvl->depth == image->base.Base.Depth); radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s miptree %p, image %p, face %d, level %d.\n", __func__, mt, image, face, level); radeon_bo_map(mt->bo, GL_TRUE); dest = mt->bo->ptr + dstlvl->faces[face].offset; if (image->mt) { /* Format etc. should match, so we really just need a memcpy(). * In fact, that memcpy() could be done by the hardware in many * cases, provided that we have a proper memory manager. */ assert(mt->mesaFormat == image->base.Base.TexFormat); radeon_mipmap_level *srclvl = &image->mt->levels[image->base.Base.Level]; assert(image->base.Base.Level == level); assert(srclvl->size == dstlvl->size); assert(srclvl->rowstride == dstlvl->rowstride); radeon_bo_map(image->mt->bo, GL_FALSE); memcpy(dest, image->mt->bo->ptr + srclvl->faces[face].offset, dstlvl->size); radeon_bo_unmap(image->mt->bo); radeon_miptree_unreference(&image->mt); } radeon_bo_unmap(mt->bo); radeon_miptree_reference(mt, &image->mt); }
static void unmap_override(GLcontext *ctx, radeonTexObj *t) { radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]); radeon_bo_unmap(t->bo); img->base.Data = NULL; }
static void radeon_swrast_unmap_image(radeonContextPtr rmesa, radeon_texture_image *image) { if (image && image->mt) { image->base.Map = NULL; radeon_bo_unmap(image->mt->bo); } }
struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle, unsigned size, unsigned alignment, void *ptr) { struct radeon_bo *bo; int r; bo = calloc(1, sizeof(*bo)); if (bo == NULL) { return NULL; } bo->size = size; bo->handle = handle; bo->refcount = 1; bo->alignment = alignment; if (handle) { struct drm_gem_open open_arg; memset(&open_arg, 0, sizeof(open_arg)); open_arg.name = handle; r = drmIoctl(radeon->fd, DRM_IOCTL_GEM_OPEN, &open_arg); if (r != 0) { free(bo); return NULL; } bo->handle = open_arg.handle; bo->size = open_arg.size; } else { struct drm_radeon_gem_create args; args.size = size; args.alignment = alignment; args.initial_domain = RADEON_GEM_DOMAIN_CPU; args.flags = 0; args.handle = 0; r = drmCommandWriteRead(radeon->fd, DRM_RADEON_GEM_CREATE, &args, sizeof(args)); bo->handle = args.handle; if (r) { fprintf(stderr, "Failed to allocate :\n"); fprintf(stderr, " size : %d bytes\n", size); fprintf(stderr, " alignment : %d bytes\n", alignment); free(bo); return NULL; } } if (ptr) { if (radeon_bo_map(radeon, bo)) { fprintf(stderr, "%s failed to copy data into bo\n", __func__); return radeon_bo_decref(radeon, bo); } memcpy(bo->data, ptr, size); radeon_bo_unmap(radeon, bo); } return bo; }
void radeon_teximage_unmap(radeon_texture_image *image) { radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(img %p)\n", __func__, image); if (image->mt) { assert(image->base.Map); image->base.Map = 0; radeon_bo_unmap(image->mt->bo); } }
static void evergreenSetupIndexBuffer(GLcontext *ctx, const struct _mesa_index_buffer *mesa_ind_buf) { context_t *context = EVERGREEN_CONTEXT(ctx); if (!mesa_ind_buf) { context->ind_buf.bo = NULL; return; } #if MESA_BIG_ENDIAN if (mesa_ind_buf->type == GL_UNSIGNED_INT) #else if (mesa_ind_buf->type != GL_UNSIGNED_BYTE) #endif { const GLvoid *src_ptr; GLvoid *dst_ptr; GLboolean mapped_named_bo = GL_FALSE; if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer) { ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY_ARB, mesa_ind_buf->obj); assert(mesa_ind_buf->obj->Pointer != NULL); mapped_named_bo = GL_TRUE; } src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr); const GLuint size = mesa_ind_buf->count * getTypeSize(mesa_ind_buf->type); radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo, &context->ind_buf.bo_offset, size, 4); radeon_bo_map(context->ind_buf.bo, 1); assert(context->ind_buf.bo->ptr != NULL); dst_ptr = ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset); memcpy(dst_ptr, src_ptr, size); radeon_bo_unmap(context->ind_buf.bo); context->ind_buf.is_32bit = (mesa_ind_buf->type == GL_UNSIGNED_INT); context->ind_buf.count = mesa_ind_buf->count; if (mapped_named_bo) { ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, mesa_ind_buf->obj); } } else { evergreenFixupIndexBuffer(ctx, mesa_ind_buf); } }
/** * Called via glGetBufferSubDataARB() */ static void radeonGetBufferSubData(struct gl_context * ctx, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data, struct gl_buffer_object *obj) { struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); radeon_bo_map(radeon_obj->bo, GL_FALSE); memcpy(data, radeon_obj->bo->ptr + offset, size); radeon_bo_unmap(radeon_obj->bo); }
/** * Called via glDeleteBuffersARB(). */ static void radeonDeleteBufferObject(struct gl_context * ctx, struct gl_buffer_object *obj) { struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); if (obj->Pointer) { radeon_bo_unmap(radeon_obj->bo); } if (radeon_obj->bo) { radeon_bo_unref(radeon_obj->bo); } free(radeon_obj); }
/** * Called via glUnmapBufferARB() */ static GLboolean radeonUnmapBuffer(struct gl_context * ctx, struct gl_buffer_object *obj) { struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); if (radeon_obj->bo != NULL) { radeon_bo_unmap(radeon_obj->bo); } obj->Pointer = NULL; obj->Offset = 0; obj->Length = 0; return GL_TRUE; }
static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) { if (pixmap->refcnt == 1) { if (pixmap->devPrivate.ptr) { struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap); if (bo) radeon_bo_unmap(bo); } glamor_egl_destroy_textured_pixmap(pixmap); radeon_set_pixmap_bo(pixmap, NULL); } fbDestroyPixmap(pixmap); return TRUE; }
static void radeonQueryGetResult(struct gl_context *ctx, struct gl_query_object *q) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); struct radeon_query_object *query = (struct radeon_query_object *)q; uint32_t *result; int i; radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s: query id %d, result %d\n", __FUNCTION__, query->Base.Id, (int) query->Base.Result); radeon_bo_map(query->bo, GL_FALSE); result = query->bo->ptr; query->Base.Result = 0; if (IS_R600_CLASS(radeon->radeonScreen)) { /* ZPASS EVENT writes alternating qwords * At query start we set the start offset to 0 and * hw writes zpass start counts to qwords 0, 2, 4, 6. * At query end we set the start offset to 8 and * hw writes zpass end counts to qwords 1, 3, 5, 7. * then we substract. MSB is the valid bit. */ for (i = 0; i < 32; i += 4) { uint64_t start = (uint64_t)LE32_TO_CPU(result[i]) | (uint64_t)LE32_TO_CPU(result[i + 1]) << 32; uint64_t end = (uint64_t)LE32_TO_CPU(result[i + 2]) | (uint64_t)LE32_TO_CPU(result[i + 3]) << 32; if ((start & 0x8000000000000000) && (end & 0x8000000000000000)) { uint64_t query_count = end - start; query->Base.Result += query_count; } radeon_print(RADEON_STATE, RADEON_TRACE, "%d start: %" PRIu64 ", end: %" PRIu64 " %" PRIu64 "\n", i, start, end, end - start); } } else { for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) { query->Base.Result += LE32_TO_CPU(result[i]); radeon_print(RADEON_STATE, RADEON_TRACE, "result[%d] = %d\n", i, LE32_TO_CPU(result[i])); } } radeon_bo_unmap(query->bo); }
compute_shader::compute_shader(r800_state* state, const std::vector<char>& binary) { const cs_image_header* header = (const cs_image_header*)&binary[0]; assert(binary.size()%4 == 0); assert(header->magic == 0x42424242); uint32_t sum = 0; for (int i = 8; i < binary.size(); i++) { sum = sum + binary[i]; } assert(header->chksum == sum); lds_alloc = header->lds_alloc; num_gprs = header->num_gprs; temp_gprs = header->temp_gprs; global_gprs = header->global_gprs; stack_size = header->stack_size; thread_num = header->thread_num; dyn_gpr_limit = header->dyn_gpr_limit; int shader_start = sizeof(cs_image_header); alloc_size = binary.size() - shader_start; if (alloc_size % 16) { alloc_size += (16 - alloc_size % 16); } binary_code_bo = state->bo_open(0, alloc_size, 0, RADEON_GEM_DOMAIN_VRAM, 0); assert(binary_code_bo != NULL); assert(radeon_bo_map(binary_code_bo, 1) == 0); memcpy(binary_code_bo->ptr, &binary[0] + shader_start, binary.size() - shader_start); radeon_bo_unmap(binary_code_bo); }
/** * Replace data in a subrange of buffer object. If the data range * specified by size + offset extends beyond the end of the buffer or * if data is NULL, no copy is performed. * Called via glBufferSubDataARB(). */ static void radeonBufferSubData(struct gl_context * ctx, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data, struct gl_buffer_object *obj) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); if (radeon_bo_is_referenced_by_cs(radeon_obj->bo, radeon->cmdbuf.cs)) { radeon_firevertices(radeon); } radeon_bo_map(radeon_obj->bo, GL_TRUE); memcpy(radeon_obj->bo->ptr + offset, data, size); radeon_bo_unmap(radeon_obj->bo); }
void r600_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer* transfer) { struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; struct r600_screen *rscreen = r600_screen(ctx->screen); struct r600_resource_texture *rtex; struct radeon_bo *bo; if (rtransfer->linear_texture) { bo = ((struct r600_resource *)rtransfer->linear_texture)->bo; } else { rtex = (struct r600_resource_texture*)transfer->resource; if (rtex->depth) { bo = rtex->uncompressed; } else { bo = ((struct r600_resource *)transfer->resource)->bo; } } radeon_bo_unmap(rscreen->rw, bo); }
static void evergreenAlignDataToDword(GLcontext *ctx, const struct gl_client_array *input, int count, struct StreamDesc *attr) { context_t *context = EVERGREEN_CONTEXT(ctx); const int dst_stride = (input->StrideB + 3) & ~3; const int size = getTypeSize(input->Type) * input->Size * count; GLboolean mapped_named_bo = GL_FALSE; radeonAllocDmaRegion(&context->radeon, &attr->bo, &attr->bo_offset, size, 32); radeon_bo_map(attr->bo, 1); if (!input->BufferObj->Pointer) { ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, input->BufferObj); mapped_named_bo = GL_TRUE; } { GLvoid *src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr); GLvoid *dst_ptr = ADD_POINTERS(attr->bo->ptr, attr->bo_offset); int i; for (i = 0; i < count; ++i) { memcpy(dst_ptr, src_ptr, input->StrideB); src_ptr += input->StrideB; dst_ptr += dst_stride; } } radeon_bo_unmap(attr->bo); if (mapped_named_bo) { ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, input->BufferObj); } attr->stride = dst_stride; }
void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj) { radeonTexObj* t = radeon_tex_obj(texObj); int face, level; radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s(%p, tex %p)\n", __func__, ctx, texObj); if (t->image_override && t->bo) unmap_override(ctx, t); /* for r100 3D sw fallbacks don't have mt */ if (!t->mt) return; for(face = 0; face < t->mt->faces; ++face) { for(level = t->minLod; level <= t->maxLod; ++level) texObj->Image[face][level]->Data = 0; } radeon_bo_unmap(t->mt->bo); }
static void radeonQueryGetResult(struct gl_context *ctx, struct gl_query_object *q) { struct radeon_query_object *query = (struct radeon_query_object *)q; uint32_t *result; int i; radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s: query id %d, result %d\n", __FUNCTION__, query->Base.Id, (int) query->Base.Result); radeon_bo_map(query->bo, GL_FALSE); result = query->bo->ptr; query->Base.Result = 0; for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) { query->Base.Result += LE32_TO_CPU(result[i]); radeon_print(RADEON_STATE, RADEON_TRACE, "result[%d] = %d\n", i, LE32_TO_CPU(result[i])); } radeon_bo_unmap(query->bo); }
/** * Allocate space for and store data in a buffer object. Any data that was * previously stored in the buffer object is lost. If data is NULL, * memory will be allocated, but no copy will occur. * Called via ctx->Driver.BufferData(). * \return GL_TRUE for success, GL_FALSE if out of memory */ static GLboolean radeonBufferData(struct gl_context * ctx, GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage, struct gl_buffer_object *obj) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); radeon_obj->Base.Size = size; radeon_obj->Base.Usage = usage; if (radeon_obj->bo != NULL) { radeon_bo_unref(radeon_obj->bo); radeon_obj->bo = NULL; } if (size != 0) { radeon_obj->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, size, 32, RADEON_GEM_DOMAIN_GTT, 0); if (!radeon_obj->bo) return GL_FALSE; if (data != NULL) { radeon_bo_map(radeon_obj->bo, GL_TRUE); memcpy(radeon_obj->bo->ptr, data, size); radeon_bo_unmap(radeon_obj->bo); } } return GL_TRUE; }
void r200FlushElts(struct gl_context *ctx) { r200ContextPtr rmesa = R200_CONTEXT(ctx); int nr, elt_used = rmesa->tcl.elt_used; radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used); assert( rmesa->radeon.dma.flush == r200FlushElts ); rmesa->radeon.dma.flush = NULL; nr = elt_used / 2; radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo); r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive); radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo); rmesa->radeon.tcl.elt_dma_bo = NULL; if (R200_ELT_BUF_SZ > elt_used) radeonReturnDmaRegion(&rmesa->radeon, R200_ELT_BUF_SZ - elt_used); }
static void r300AlignDataToDword(GLcontext *ctx, const struct gl_client_array *input, int count, struct vertex_attribute *attr) { r300ContextPtr r300 = R300_CONTEXT(ctx); const int dst_stride = (input->StrideB + 3) & ~3; const int size = getTypeSize(input->Type) * input->Size * count; GLboolean mapped_named_bo = GL_FALSE; radeonAllocDmaRegion(&r300->radeon, &attr->bo, &attr->bo_offset, size, 32); radeon_bo_map(attr->bo, 1); if (!input->BufferObj->Pointer) { ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, input->BufferObj); mapped_named_bo = GL_TRUE; } radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT, "%s. Vertex alignment doesn't match hw requirements.\n", __func__); { GLvoid *src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr); GLvoid *dst_ptr = ADD_POINTERS(attr->bo->ptr, attr->bo_offset); int i; for (i = 0; i < count; ++i) { memcpy(dst_ptr, src_ptr, input->StrideB); src_ptr += input->StrideB; dst_ptr += dst_stride; } } if (mapped_named_bo) { ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, input->BufferObj); } radeon_bo_unmap(attr->bo); attr->stride = dst_stride; }
static cairo_status_t radeon_surface_flush (void *abstract_surface, unsigned flags) { radeon_surface_t *surface = abstract_surface; cairo_status_t status; if (flags) return CAIRO_STATUS_SUCCESS; if (surface->base.fallback == NULL) return CAIRO_STATUS_SUCCESS; /* kill any outstanding maps */ cairo_surface_finish (surface->base.fallback); status = cairo_surface_status (surface->base.fallback); cairo_surface_destroy (surface->base.fallback); surface->base.fallback = NULL; radeon_bo_unmap (to_radeon_bo (surface->base.bo)); return status; }
static void cs_gem_dump_bof(struct radeon_cs_int *cs) { struct cs_gem *csg = (struct cs_gem*)cs; struct radeon_cs_manager_gem *csm; bof_t *bcs, *blob, *array, *bo, *size, *handle, *device_id, *root; char tmp[256]; unsigned i; csm = (struct radeon_cs_manager_gem *)cs->csm; root = device_id = bcs = blob = array = bo = size = handle = NULL; root = bof_object(); if (root == NULL) goto out_err; device_id = bof_int32(csm->device_id); if (device_id == NULL) return; if (bof_object_set(root, "device_id", device_id)) goto out_err; bof_decref(device_id); device_id = NULL; /* dump relocs */ blob = bof_blob(csg->nrelocs * 16, csg->relocs); if (blob == NULL) goto out_err; if (bof_object_set(root, "reloc", blob)) goto out_err; bof_decref(blob); blob = NULL; /* dump cs */ blob = bof_blob(cs->cdw * 4, cs->packets); if (blob == NULL) goto out_err; if (bof_object_set(root, "pm4", blob)) goto out_err; bof_decref(blob); blob = NULL; /* dump bo */ array = bof_array(); if (array == NULL) goto out_err; for (i = 0; i < csg->base.crelocs; i++) { bo = bof_object(); if (bo == NULL) goto out_err; size = bof_int32(csg->relocs_bo[i]->size); if (size == NULL) goto out_err; if (bof_object_set(bo, "size", size)) goto out_err; bof_decref(size); size = NULL; handle = bof_int32(csg->relocs_bo[i]->handle); if (handle == NULL) goto out_err; if (bof_object_set(bo, "handle", handle)) goto out_err; bof_decref(handle); handle = NULL; radeon_bo_map((struct radeon_bo*)csg->relocs_bo[i], 0); blob = bof_blob(csg->relocs_bo[i]->size, csg->relocs_bo[i]->ptr); radeon_bo_unmap((struct radeon_bo*)csg->relocs_bo[i]); if (blob == NULL) goto out_err; if (bof_object_set(bo, "data", blob)) goto out_err; bof_decref(blob); blob = NULL; if (bof_array_append(array, bo)) goto out_err; bof_decref(bo); bo = NULL; } if (bof_object_set(root, "bo", array)) goto out_err; sprintf(tmp, "d-0x%04X-%08d.bof", csm->device_id, csm->nbof++); bof_dump_file(root, tmp); out_err: bof_decref(blob); bof_decref(array); bof_decref(bo); bof_decref(size); bof_decref(handle); bof_decref(device_id); bof_decref(root); }
static GLboolean do_blit_readpixels(struct gl_context * ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid * pixels) { radeonContextPtr radeon = RADEON_CONTEXT(ctx); const struct radeon_renderbuffer *rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); const gl_format dst_format = gl_format_and_type_to_mesa_format(format, type); unsigned dst_rowstride, dst_imagesize, aligned_rowstride, flip_y; struct radeon_bo *dst_buffer; GLint dst_x = 0, dst_y = 0; intptr_t dst_offset; /* It's not worth if number of pixels to copy is really small */ if (width * height < 100) { return GL_FALSE; } if (dst_format == MESA_FORMAT_NONE || !radeon->vtbl.check_blit(dst_format) || !radeon->vtbl.blit) { return GL_FALSE; } if (ctx->_ImageTransferState || ctx->Color._LogicOpEnabled) { return GL_FALSE; } if (pack->SwapBytes || pack->LsbFirst) { return GL_FALSE; } if (pack->RowLength > 0) { dst_rowstride = pack->RowLength; } else { dst_rowstride = width; } if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) { return GL_TRUE; } assert(x >= 0 && y >= 0); aligned_rowstride = get_texture_image_row_stride(radeon, dst_format, dst_rowstride, 0); dst_rowstride *= _mesa_get_format_bytes(dst_format); if (_mesa_is_bufferobj(pack->BufferObj) && aligned_rowstride != dst_rowstride) return GL_FALSE; dst_imagesize = get_texture_image_size(dst_format, aligned_rowstride, height, 1, 0); if (!_mesa_is_bufferobj(pack->BufferObj)) { dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0); dst_offset = 0; } else { dst_buffer = get_radeon_buffer_object(pack->BufferObj)->bo; dst_offset = (intptr_t)pixels; } /* Disable source Y flipping for FBOs */ flip_y = (ctx->ReadBuffer->Name == 0); if (pack->Invert) { y = rrb->base.Height - height - y; flip_y = !flip_y; } if (radeon->vtbl.blit(ctx, rrb->bo, rrb->draw_offset, rrb->base.Format, rrb->pitch / rrb->cpp, rrb->base.Width, rrb->base.Height, x, y, dst_buffer, dst_offset, dst_format, aligned_rowstride / _mesa_get_format_bytes(dst_format), width, height, 0, /* dst_x */ 0, /* dst_y */ width, height, flip_y)) { if (!_mesa_is_bufferobj(pack->BufferObj)) { radeon_bo_map(dst_buffer, 0); copy_rows(pixels, dst_rowstride, dst_buffer->ptr, aligned_rowstride, height, dst_rowstride); radeon_bo_unmap(dst_buffer); radeon_bo_unref(dst_buffer); } return GL_TRUE; } if (!_mesa_is_bufferobj(pack->BufferObj)) radeon_bo_unref(dst_buffer); return GL_FALSE; }
static Bool RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) { ScreenPtr pScreen = pDst->drawable.pScreen; RINFO_FROM_SCREEN(pScreen); struct radeon_exa_pixmap_priv *driver_priv; struct radeon_bo *scratch = NULL; struct radeon_bo *copy_dst; unsigned char *dst; unsigned size; uint32_t datatype = 0; uint32_t dst_domain; uint32_t dst_pitch_offset; unsigned bpp = pDst->drawable.bitsPerPixel; uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); uint32_t copy_pitch; uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; int ret; Bool flush = TRUE; Bool r; int i; if (bpp < 8) return FALSE; driver_priv = exaGetPixmapDriverPrivate(pDst); if (!driver_priv || !driver_priv->bo) return FALSE; #if X_BYTE_ORDER == X_BIG_ENDIAN switch (bpp) { case 32: swap = RADEON_HOST_DATA_SWAP_32BIT; break; case 16: swap = RADEON_HOST_DATA_SWAP_16BIT; break; } #endif /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */ copy_dst = driver_priv->bo; copy_pitch = pDst->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { flush = FALSE; if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) && !(dst_domain & RADEON_GEM_DOMAIN_VRAM)) goto copy; } /* use cpu copy for fast fb access */ if (info->is_fast_fb) goto copy; } size = scratch_pitch * h; scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); if (scratch == NULL) { goto copy; } radeon_cs_space_reset_bos(info->cs); radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM); radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0); ret = radeon_cs_space_check(info->cs); if (ret) { goto copy; } copy_dst = scratch; copy_pitch = scratch_pitch; flush = FALSE; copy: if (flush) radeon_cs_flush_indirect(pScrn); ret = radeon_bo_map(copy_dst, 0); if (ret) { r = FALSE; goto out; } r = TRUE; size = w * bpp / 8; dst = copy_dst->ptr; if (copy_dst == driver_priv->bo) dst += y * copy_pitch + x * bpp / 8; for (i = 0; i < h; i++) { RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap); src += src_pitch; } radeon_bo_unmap(copy_dst); if (copy_dst == scratch) { RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype); RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset); RADEON_SWITCH_TO_2D(); RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16, dst_pitch_offset, 0, 0, x, y, w, h, RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM); } out: if (scratch) radeon_bo_unref(scratch); return r; }
static Bool RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch) { RINFO_FROM_SCREEN(pSrc->drawable.pScreen); struct radeon_exa_pixmap_priv *driver_priv; struct radeon_bo *scratch = NULL; struct radeon_bo *copy_src; unsigned size; uint32_t datatype = 0; uint32_t src_domain = 0; uint32_t src_pitch_offset; unsigned bpp = pSrc->drawable.bitsPerPixel; uint32_t scratch_pitch = RADEON_ALIGN(w * bpp / 8, 64); uint32_t copy_pitch; uint32_t swap = RADEON_HOST_DATA_SWAP_NONE; int ret; Bool flush = FALSE; Bool r; if (bpp < 8) return FALSE; driver_priv = exaGetPixmapDriverPrivate(pSrc); if (!driver_priv || !driver_priv->bo) return FALSE; #if X_BYTE_ORDER == X_BIG_ENDIAN switch (bpp) { case 32: swap = RADEON_HOST_DATA_SWAP_32BIT; break; case 16: swap = RADEON_HOST_DATA_SWAP_16BIT; break; } #endif /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ copy_src = driver_priv->bo; copy_pitch = pSrc->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { src_domain = radeon_bo_get_src_domain(driver_priv->bo); if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) src_domain = 0; else /* A write may be scheduled */ flush = TRUE; } if (!src_domain) radeon_bo_is_busy(driver_priv->bo, &src_domain); if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) goto copy; } size = scratch_pitch * h; scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); if (scratch == NULL) { goto copy; } radeon_cs_space_reset_bos(info->cs); radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT); ret = radeon_cs_space_check(info->cs); if (ret) { goto copy; } RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype); RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); RADEON_SWITCH_TO_2D(); RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset, scratch_pitch << 16, x, y, 0, 0, w, h, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_GTT); copy_src = scratch; copy_pitch = scratch_pitch; flush = TRUE; copy: if (flush) FLUSH_RING(); ret = radeon_bo_map(copy_src, 0); if (ret) { ErrorF("failed to map pixmap: %d\n", ret); r = FALSE; goto out; } r = TRUE; w *= bpp / 8; if (copy_src == driver_priv->bo) size = y * copy_pitch + x * bpp / 8; else size = 0; while (h--) { RADEONCopySwap((uint8_t*)dst, copy_src->ptr + size, w, swap); size += copy_pitch; dst += dst_pitch; } radeon_bo_unmap(copy_src); out: if (scratch) radeon_bo_unref(scratch); return r; }