static __DRIimage * intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) { __DRIimage *image; image = calloc(1, sizeof *image); if (image == NULL) return NULL; intel_region_reference(&image->region, orig_image->region); if (image->region == NULL) { free(image); return NULL; } image->internal_format = orig_image->internal_format; image->planar_format = orig_image->planar_format; image->dri_format = orig_image->dri_format; image->format = orig_image->format; image->offset = orig_image->offset; image->width = orig_image->width; image->height = orig_image->height; image->tile_x = orig_image->tile_x; image->tile_y = orig_image->tile_y; image->data = loaderPrivate; memcpy(image->strides, orig_image->strides, sizeof(image->strides)); memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets)); return image; }
/** * Sets up a DRIImage structure to point to our shared image in a region */ static void intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image, struct intel_mipmap_tree *mt, GLuint level, GLuint zoffset) { unsigned int draw_x, draw_y; uint32_t mask_x, mask_y; intel_miptree_make_shareable(brw, mt); intel_miptree_check_level_layer(mt, level, zoffset); intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false); intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y); image->width = mt->level[level].width; image->height = mt->level[level].height; image->tile_x = draw_x & mask_x; image->tile_y = draw_y & mask_y; image->offset = intel_region_get_aligned_offset(mt->region, draw_x & ~mask_x, draw_y & ~mask_y, false); intel_region_reference(&image->region, mt->region); }
static __DRIimage * intel_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; struct intel_context *intel = context->driverPrivate; struct gl_renderbuffer *rb; struct intel_renderbuffer *irb; rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); if (!rb) { _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } irb = intel_renderbuffer(rb); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->offset = 0; image->data = loaderPrivate; intel_region_reference(&image->region, irb->mt->region); intel_setup_image_from_dimensions(image); image->dri_format = driGLFormatToImageFormat(image->format); rb->NeedsFinishRenderTexture = true; return image; }
static __DRIimage * intel_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; struct brw_context *brw = context->driverPrivate; struct gl_context *ctx = &brw->ctx; struct gl_renderbuffer *rb; struct intel_renderbuffer *irb; rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb) { _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } irb = intel_renderbuffer(rb); intel_miptree_make_shareable(brw, irb->mt); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->offset = 0; image->data = loaderPrivate; intel_region_reference(&image->region, irb->mt->region); intel_setup_image_from_dimensions(image); image->dri_format = intel_dri_format(image->format); image->has_depthstencil = irb->mt->stencil_mt? true : false; rb->NeedsFinishRenderTexture = true; return image; }
void intel_renderbuffer_set_region(struct intel_renderbuffer *rb, struct intel_region *region) { struct intel_region *old; old = rb->region; rb->region = NULL; intel_region_reference(&rb->region, region); intel_region_release(&old); }
static __DRIimage * intel_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; struct intel_context *intel = context->driverPrivate; struct gl_renderbuffer *rb; struct intel_renderbuffer *irb; rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); if (!rb) { _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } irb = intel_renderbuffer(rb); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->offset = 0; image->data = loaderPrivate; intel_region_reference(&image->region, irb->mt->region); switch (image->format) { case MESA_FORMAT_RGB565: image->dri_format = __DRI_IMAGE_FORMAT_RGB565; break; case MESA_FORMAT_XRGB8888: image->dri_format = __DRI_IMAGE_FORMAT_XRGB8888; break; case MESA_FORMAT_ARGB8888: image->dri_format = __DRI_IMAGE_FORMAT_ARGB8888; break; case MESA_FORMAT_RGBA8888_REV: image->dri_format = __DRI_IMAGE_FORMAT_ABGR8888; break; case MESA_FORMAT_R8: image->dri_format = __DRI_IMAGE_FORMAT_R8; break; case MESA_FORMAT_RG88: image->dri_format = __DRI_IMAGE_FORMAT_GR88; break; } rb->NeedsFinishRenderTexture = true; return image; }
void intel_renderbuffer_set_region(struct intel_renderbuffer *rb, struct intel_region *region) { struct intel_region *old; old = rb->region; rb->region = NULL; intel_region_reference(&rb->region, region); intel_region_release(&old); rb->pfMap = region->map; rb->pfPitch = region->pitch; }
struct intel_mipmap_tree * intel_miptree_create_for_region(struct intel_context *intel, GLenum target, GLenum internal_format, GLuint first_level, GLuint last_level, struct intel_region *region, GLuint depth0, GLuint compress_byte) { struct intel_mipmap_tree *mt; mt = intel_miptree_create_internal(intel, target, internal_format, first_level, last_level, region->width, region->height, 1, region->cpp, compress_byte); if (!mt) return mt; #if 0 if (mt->pitch != region->pitch) { fprintf(stderr, "region pitch (%d) doesn't match mipmap tree pitch (%d)\n", region->pitch, mt->pitch); free(mt); return NULL; } #else /* The mipmap tree pitch is aligned to 64 bytes to make sure render * to texture works, but we don't need that for texturing from a * pixmap. Just override it here. */ mt->pitch = region->pitch; #endif intel_region_reference(&mt->region, region); return mt; }
struct intel_mipmap_tree * intel_miptree_create_for_region(struct intel_context *intel, GLenum target, GLenum internal_format, GLuint first_level, GLuint last_level, struct intel_region *region, GLuint depth0, GLuint compress_byte) { struct intel_mipmap_tree *mt; mt = intel_miptree_create_internal(intel, target, internal_format, first_level, last_level, region->width, region->height, 1, region->cpp, compress_byte, I915_TILING_NONE); if (!mt) return mt; intel_region_reference(&mt->region, region); return mt; }
static __DRIimage * intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) { __DRIimage *image; image = CALLOC(sizeof *image); if (image == NULL) return NULL; intel_region_reference(&image->region, orig_image->region); if (image->region == NULL) { FREE(image); return NULL; } image->internal_format = orig_image->internal_format; image->usage = orig_image->usage; image->dri_format = orig_image->dri_format; image->format = orig_image->format; image->offset = orig_image->offset; image->data = loaderPrivate; return image; }
void intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) { struct gl_framebuffer *fb = drawable->driverPrivate; struct intel_renderbuffer *rb; struct intel_region *region, *depth_region; struct intel_context *intel = context->driverPrivate; struct intel_renderbuffer *front_rb, *back_rb, *depth_rb, *stencil_rb; __DRIbuffer *buffers = NULL; __DRIscreen *screen; int i, count; unsigned int attachments[10]; const char *region_name; /* If we're rendering to the fake front buffer, make sure all the * pending drawing has landed on the real front buffer. Otherwise * when we eventually get to DRI2GetBuffersWithFormat the stale * real front buffer contents will get copied to the new fake front * buffer. */ if (intel->is_front_buffer_rendering) intel_flush(&intel->ctx, GL_FALSE); /* Set this up front, so that in case our buffers get invalidated * while we're getting new buffers, we don't clobber the stamp and * thus ignore the invalidate. */ drawable->lastStamp = drawable->dri2.stamp; if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); screen = intel->intelScreen->driScrnPriv; if (screen->dri2.loader && (screen->dri2.loader->base.version > 2) && (screen->dri2.loader->getBuffersWithFormat != NULL)) { front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL); i = 0; if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb) { attachments[i++] = __DRI_BUFFER_FRONT_LEFT; attachments[i++] = intel_bits_per_pixel(front_rb); } if (back_rb) { attachments[i++] = __DRI_BUFFER_BACK_LEFT; attachments[i++] = intel_bits_per_pixel(back_rb); } if ((depth_rb != NULL) && (stencil_rb != NULL)) { attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; attachments[i++] = intel_bits_per_pixel(depth_rb); } else if (depth_rb != NULL) { attachments[i++] = __DRI_BUFFER_DEPTH; attachments[i++] = intel_bits_per_pixel(depth_rb); } else if (stencil_rb != NULL) { attachments[i++] = __DRI_BUFFER_STENCIL; attachments[i++] = intel_bits_per_pixel(stencil_rb); } buffers = (*screen->dri2.loader->getBuffersWithFormat)(drawable, &drawable->w, &drawable->h, attachments, i / 2, &count, drawable->loaderPrivate); } else if (screen->dri2.loader) { i = 0; if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT)) attachments[i++] = __DRI_BUFFER_FRONT_LEFT; if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT)) attachments[i++] = __DRI_BUFFER_BACK_LEFT; if (intel_get_renderbuffer(fb, BUFFER_DEPTH)) attachments[i++] = __DRI_BUFFER_DEPTH; if (intel_get_renderbuffer(fb, BUFFER_STENCIL)) attachments[i++] = __DRI_BUFFER_STENCIL; buffers = (*screen->dri2.loader->getBuffers)(drawable, &drawable->w, &drawable->h, attachments, i, &count, drawable->loaderPrivate); } if (buffers == NULL) return; drawable->x = 0; drawable->y = 0; drawable->backX = 0; drawable->backY = 0; drawable->numClipRects = 1; drawable->pClipRects[0].x1 = 0; drawable->pClipRects[0].y1 = 0; drawable->pClipRects[0].x2 = drawable->w; drawable->pClipRects[0].y2 = drawable->h; drawable->numBackClipRects = 1; drawable->pBackClipRects[0].x1 = 0; drawable->pBackClipRects[0].y1 = 0; drawable->pBackClipRects[0].x2 = drawable->w; drawable->pBackClipRects[0].y2 = drawable->h; depth_region = NULL; for (i = 0; i < count; i++) { switch (buffers[i].attachment) { case __DRI_BUFFER_FRONT_LEFT: rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); region_name = "dri2 front buffer"; break; case __DRI_BUFFER_FAKE_FRONT_LEFT: rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); region_name = "dri2 fake front buffer"; break; case __DRI_BUFFER_BACK_LEFT: rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); region_name = "dri2 back buffer"; break; case __DRI_BUFFER_DEPTH: rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); region_name = "dri2 depth buffer"; break; case __DRI_BUFFER_DEPTH_STENCIL: rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); region_name = "dri2 depth / stencil buffer"; break; case __DRI_BUFFER_STENCIL: rb = intel_get_renderbuffer(fb, BUFFER_STENCIL); region_name = "dri2 stencil buffer"; break; case __DRI_BUFFER_ACCUM: default: fprintf(stderr, "unhandled buffer attach event, attacment type %d\n", buffers[i].attachment); return; } if (rb == NULL) continue; if (rb->region && rb->region->name == buffers[i].name) continue; if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "attaching buffer %d, at %d, cpp %d, pitch %d\n", buffers[i].name, buffers[i].attachment, buffers[i].cpp, buffers[i].pitch); if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_region) { if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "(reusing depth buffer as stencil)\n"); intel_region_reference(®ion, depth_region); } else region = intel_region_alloc_for_handle(intel, buffers[i].cpp, drawable->w, drawable->h, buffers[i].pitch / buffers[i].cpp, buffers[i].name, region_name); if (buffers[i].attachment == __DRI_BUFFER_DEPTH) depth_region = region; intel_renderbuffer_set_region(intel, rb, region); intel_region_release(®ion); if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) { rb = intel_get_renderbuffer(fb, BUFFER_STENCIL); if (rb != NULL) { struct intel_region *stencil_region = NULL; if (rb->region && rb->region->name == buffers[i].name) continue; intel_region_reference(&stencil_region, region); intel_renderbuffer_set_region(intel, rb, stencil_region); intel_region_release(&stencil_region); } } } driUpdateFramebufferSize(&intel->ctx, drawable); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(GLcontext * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image; GLuint dst_x, dst_y; (void) fb; ASSERT(newImage); intel_image = intel_texture_image(newImage); if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } else if (!irb) { irb = intel_wrap_texture(ctx, newImage); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!intel_update_wrapper(ctx, irb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, irb->Base.RefCount); /* point the renderbufer's region to the texture image region */ if (irb->region != intel_image->mt->region) { if (irb->region) intel_region_release(&irb->region); intel_region_reference(&irb->region, intel_image->mt->region); } /* compute offset of the particular 2D image within the texture region */ intel_miptree_get_image_offset(intel_image->mt, att->TextureLevel, att->CubeMapFace, att->Zoffset, &dst_x, &dst_y); intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch + dst_x) * intel_image->mt->cpp; intel_image->mt->region->draw_x = dst_x; intel_image->mt->region->draw_y = dst_y; intel_image->used_as_render_target = GL_TRUE; /* update drawing region, etc */ intel_draw_buffer(ctx, fb); }
/** * Binds a region to a texture image, like it was uploaded by glTexImage2D(). * * Used for GLX_EXT_texture_from_pixmap and EGL image extensions, */ static void intel_set_texture_image_region(struct gl_context *ctx, struct gl_texture_image *image, struct intel_region *region, GLenum target, GLenum internalFormat, gl_format format, uint32_t offset, GLuint width, GLuint height, GLuint tile_x, GLuint tile_y) { struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intel_image = intel_texture_image(image); struct gl_texture_object *texobj = image->TexObject; struct intel_texture_object *intel_texobj = intel_texture_object(texobj); bool has_surface_tile_offset = false; uint32_t draw_x, draw_y; _mesa_init_teximage_fields(&intel->ctx, image, width, height, 1, 0, internalFormat, format); ctx->Driver.FreeTextureImageBuffer(ctx, image); intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat, 0, 0, width, height, 1, true, 0 /* num_samples */); if (intel_image->mt == NULL) return; intel_region_reference(&intel_image->mt->region, region); intel_image->mt->total_width = width; intel_image->mt->total_height = height; intel_image->mt->level[0].slice[0].x_offset = tile_x; intel_image->mt->level[0].slice[0].y_offset = tile_y; intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y); #ifndef I915 has_surface_tile_offset = brw_context(ctx)->has_surface_tile_offset; #endif /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has * trouble resolving back to destination image due to alignment issues. */ if (!has_surface_tile_offset && (draw_x != 0 || draw_y != 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, __func__); intel_miptree_release(&intel_image->mt); return; } intel_texobj->needs_validate = true; intel_image->mt->offset = offset; assert(region->pitch % region->cpp == 0); intel_image->base.RowStride = region->pitch / region->cpp; /* Immediately validate the image to the object. */ intel_miptree_reference(&intel_texobj->mt, intel_image->mt); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(GLcontext * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image; GLuint imageOffset; (void) fb; ASSERT(newImage); if (!irb) { irb = intel_wrap_texture(ctx, newImage); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!intel_update_wrapper(ctx, irb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, irb->Base.RefCount); /* point the renderbufer's region to the texture image region */ intel_image = intel_texture_image(newImage); if (irb->region != intel_image->mt->region) { if (irb->region) intel_region_release(&irb->region); intel_region_reference(&irb->region, intel_image->mt->region); } /* compute offset of the particular 2D image within the texture region */ imageOffset = intel_miptree_image_offset(intel_image->mt, att->CubeMapFace, att->TextureLevel); if (att->Texture->Target == GL_TEXTURE_3D) { const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt, att->TextureLevel); imageOffset += offsets[att->Zoffset]; } /* store that offset in the region */ intel_image->mt->region->draw_offset = imageOffset; /* update drawing region, etc */ intel_draw_buffer(ctx, fb); }