#include "teximage.h"
#include "texobj.h"
#include "fbobject.h"
+#include "framebuffer.h"
#include "buffers.h"
#include "state.h"
#include "mtypes.h"
#include "meta.h"
+/**
+ * Create a texture image that wraps a renderbuffer.
+ */
+static struct gl_texture_image *
+wrap_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
+{
+ GLenum texTarget;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ if (rb->NumSamples > 1)
+ texTarget = GL_TEXTURE_2D_MULTISAMPLE;
+ else
+ texTarget = GL_TEXTURE_2D;
+
+ /* Texture ID is not significant since it never goes into the hash table */
+ texObj = ctx->Driver.NewTextureObject(ctx, 0, texTarget);
+ assert(texObj);
+ if (!texObj)
+ return NULL;
+
+ texImage = _mesa_get_tex_image(ctx, texObj, texTarget, 0);
+ assert(texImage);
+ if (!texImage)
+ return NULL;
+
+ if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
+ _mesa_problem(ctx, "Failed to create texture from renderbuffer");
+ return NULL;
+ }
+
+ if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
+ rb->NeedsFinishRenderTexture = true;
+ ctx->Driver.FinishRenderTexture(ctx, rb);
+ }
+
+ return texImage;
+}
+
+
/* This function makes a texture view without bothering with all of the API
* checks. Most of them are the same for CopyTexSubImage so checking would
* be redundant. The one major difference is that we don't check for
0, internal_format,
GL_NONE, GL_NONE);
- if (!ctx->Driver.TestProxyTexImage(ctx, tex_obj->Target, 0, tex_format,
- tex_image->Width, tex_image->Height,
- tex_image->Depth, 0)) {
+ if (!ctx->Driver.TestProxyTexImage(ctx, tex_obj->Target, 1, 0, tex_format,
+ 1, tex_image->Width, tex_image->Height,
+ tex_image->Depth)) {
_mesa_DeleteTextures(1, view_tex_name);
*view_tex_name = 0;
return false;
}
+ assert(tex_obj->Target != 0);
+ assert(tex_obj->TargetIndex < NUM_TEXTURE_TARGETS);
+
view_tex_obj->Target = tex_obj->Target;
+ view_tex_obj->TargetIndex = tex_obj->TargetIndex;
*view_tex_image = _mesa_get_tex_image(ctx, view_tex_obj, tex_obj->Target, 0);
view_tex_obj->NumLayers = tex_obj->NumLayers;
view_tex_obj->Immutable = tex_obj->Immutable;
view_tex_obj->ImmutableLevels = tex_obj->ImmutableLevels;
- view_tex_obj->Target = tex_obj->Target;
if (ctx->Driver.TextureView != NULL &&
!ctx->Driver.TextureView(ctx, view_tex_obj, tex_obj)) {
bool
_mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx,
struct gl_texture_image *src_tex_image,
+ struct gl_renderbuffer *src_renderbuffer,
int src_x, int src_y, int src_z,
struct gl_texture_image *dst_tex_image,
+ struct gl_renderbuffer *dst_renderbuffer,
int dst_x, int dst_y, int dst_z,
int src_width, int src_height)
{
+ mesa_format src_format, dst_format;
+ GLint src_internal_format, dst_internal_format;
GLuint src_view_texture = 0;
struct gl_texture_image *src_view_tex_image;
- GLuint fbos[2];
+ struct gl_framebuffer *readFb;
+ struct gl_framebuffer *drawFb = NULL;
bool success = false;
GLbitfield mask;
GLenum status, attachment;
- if (_mesa_is_format_compressed(dst_tex_image->TexFormat))
+ if (src_renderbuffer) {
+ src_format = src_renderbuffer->Format;
+ src_internal_format = src_renderbuffer->InternalFormat;
+ } else {
+ assert(src_tex_image);
+ src_format = src_tex_image->TexFormat;
+ src_internal_format = src_tex_image->InternalFormat;
+ }
+
+ if (dst_renderbuffer) {
+ dst_format = dst_renderbuffer->Format;
+ dst_internal_format = dst_renderbuffer->InternalFormat;
+ } else {
+ assert(dst_tex_image);
+ dst_format = dst_tex_image->TexFormat;
+ dst_internal_format = dst_tex_image->InternalFormat;
+ }
+
+ if (_mesa_is_format_compressed(src_format))
return false;
- if (_mesa_is_format_compressed(src_tex_image->TexFormat))
+ if (_mesa_is_format_compressed(dst_format))
return false;
- if (src_tex_image->InternalFormat == dst_tex_image->InternalFormat) {
+ if (src_internal_format == dst_internal_format) {
src_view_tex_image = src_tex_image;
} else {
+ if (src_renderbuffer) {
+ assert(src_tex_image == NULL);
+ src_tex_image = wrap_renderbuffer(ctx, src_renderbuffer);
+ }
if (!make_view(ctx, src_tex_image, &src_view_tex_image, &src_view_texture,
- dst_tex_image->InternalFormat))
+ dst_internal_format))
goto cleanup;
}
/* We really only need to stash the bound framebuffers and scissor. */
_mesa_meta_begin(ctx, MESA_META_SCISSOR);
- _mesa_GenFramebuffers(2, fbos);
- _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
- _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
+ readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
+ if (readFb == NULL)
+ goto meta_end;
+
+ drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
+ if (drawFb == NULL)
+ goto meta_end;
- switch (_mesa_get_format_base_format(src_tex_image->TexFormat)) {
+ _mesa_bind_framebuffers(ctx, drawFb, readFb);
+
+ switch (_mesa_get_format_base_format(src_format)) {
case GL_DEPTH_COMPONENT:
attachment = GL_DEPTH_ATTACHMENT;
mask = GL_DEPTH_BUFFER_BIT;
_mesa_ReadBuffer(GL_COLOR_ATTACHMENT0);
}
- _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, attachment,
- src_view_tex_image, src_z);
+ if (src_view_tex_image) {
+ /* Prefer the tex image because, even if we have a renderbuffer, we may
+ * have had to wrap it in a texture view.
+ */
+ _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, attachment,
+ src_view_tex_image, src_z);
+ } else {
+ _mesa_framebuffer_renderbuffer(ctx, ctx->ReadBuffer, attachment,
+ src_renderbuffer);
+ }
- status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer);
if (status != GL_FRAMEBUFFER_COMPLETE)
goto meta_end;
- _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, attachment,
- dst_tex_image, dst_z);
+ if (dst_renderbuffer) {
+ _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, attachment,
+ dst_renderbuffer);
+ } else {
+ _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, attachment,
+ dst_tex_image, dst_z);
+ }
- status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
if (status != GL_FRAMEBUFFER_COMPLETE)
goto meta_end;
+ /* Explicitly disable sRGB encoding */
+ ctx->DrawBuffer->Visual.sRGBCapable = false;
+
/* Since we've bound a new draw framebuffer, we need to update its
* derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to
* be correct.
success = true;
meta_end:
- _mesa_DeleteFramebuffers(2, fbos);
+ _mesa_reference_framebuffer(&readFb, NULL);
+ _mesa_reference_framebuffer(&drawFb, NULL);
_mesa_meta_end(ctx);
cleanup:
_mesa_DeleteTextures(1, &src_view_texture);
+ /* If we got a renderbuffer source, delete the temporary texture */
+ if (src_renderbuffer && src_tex_image)
+ ctx->Driver.DeleteTexture(ctx, src_tex_image->TexObject);
+
return success;
}