0,0 → 1,209 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 2014 Intel Corporation. All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
*/ |
|
#include "glheader.h" |
#include "context.h" |
#include "enums.h" |
#include "imports.h" |
#include "macros.h" |
#include "teximage.h" |
#include "texobj.h" |
#include "fbobject.h" |
#include "buffers.h" |
#include "state.h" |
#include "mtypes.h" |
#include "meta.h" |
|
/* 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 |
* whether the texture is immutable or not. However, since the view will |
* be created and then immediately destroyed, this should not be a problem. |
*/ |
static bool |
make_view(struct gl_context *ctx, struct gl_texture_image *tex_image, |
struct gl_texture_image **view_tex_image, GLuint *view_tex_name, |
GLenum internal_format) |
{ |
struct gl_texture_object *tex_obj = tex_image->TexObject; |
struct gl_texture_object *view_tex_obj; |
mesa_format tex_format; |
|
/* Set up the new texture object */ |
_mesa_GenTextures(1, view_tex_name); |
view_tex_obj = _mesa_lookup_texture(ctx, *view_tex_name); |
if (!view_tex_obj) |
return false; |
|
tex_format = _mesa_choose_texture_format(ctx, view_tex_obj, tex_obj->Target, |
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)) { |
_mesa_DeleteTextures(1, view_tex_name); |
*view_tex_name = 0; |
return false; |
} |
|
view_tex_obj->Target = tex_obj->Target; |
|
*view_tex_image = _mesa_get_tex_image(ctx, view_tex_obj, tex_obj->Target, 0); |
|
if (!*view_tex_image) { |
_mesa_DeleteTextures(1, view_tex_name); |
*view_tex_name = 0; |
return false; |
} |
|
_mesa_init_teximage_fields(ctx, *view_tex_image, |
tex_image->Width, tex_image->Height, |
tex_image->Depth, |
0, internal_format, tex_format); |
|
view_tex_obj->MinLevel = tex_image->Level; |
view_tex_obj->NumLevels = 1; |
view_tex_obj->MinLayer = tex_obj->MinLayer; |
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)) { |
_mesa_DeleteTextures(1, view_tex_name); |
*view_tex_name = 0; |
return false; /* driver recorded error */ |
} |
|
return true; |
} |
|
/** A partial implementation of glCopyImageSubData |
* |
* This is a partial implementation of glCopyImageSubData that works only |
* if both textures are uncompressed and the destination texture is |
* renderable. It uses a slight abuse of a texture view (see make_view) to |
* turn the source texture into the destination texture type and then uses |
* _mesa_meta_BlitFramebuffers to do the copy. |
*/ |
bool |
_mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx, |
struct gl_texture_image *src_tex_image, |
int src_x, int src_y, int src_z, |
struct gl_texture_image *dst_tex_image, |
int dst_x, int dst_y, int dst_z, |
int src_width, int src_height) |
{ |
GLuint src_view_texture = 0; |
struct gl_texture_image *src_view_tex_image; |
GLuint fbos[2]; |
bool success = false; |
GLbitfield mask; |
GLenum status, attachment; |
|
if (_mesa_is_format_compressed(dst_tex_image->TexFormat)) |
return false; |
|
if (_mesa_is_format_compressed(src_tex_image->TexFormat)) |
return false; |
|
if (src_tex_image->InternalFormat == dst_tex_image->InternalFormat) { |
src_view_tex_image = src_tex_image; |
} else { |
if (!make_view(ctx, src_tex_image, &src_view_tex_image, &src_view_texture, |
dst_tex_image->InternalFormat)) |
goto cleanup; |
} |
|
/* We really only need to stash the bound framebuffers. */ |
_mesa_meta_begin(ctx, 0); |
|
_mesa_GenFramebuffers(2, fbos); |
_mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); |
_mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); |
|
switch (_mesa_get_format_base_format(src_tex_image->TexFormat)) { |
case GL_DEPTH_COMPONENT: |
attachment = GL_DEPTH_ATTACHMENT; |
mask = GL_DEPTH_BUFFER_BIT; |
break; |
case GL_DEPTH_STENCIL: |
attachment = GL_DEPTH_STENCIL_ATTACHMENT; |
mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; |
break; |
case GL_STENCIL_INDEX: |
attachment = GL_STENCIL_ATTACHMENT; |
mask = GL_STENCIL_BUFFER_BIT; |
break; |
default: |
attachment = GL_COLOR_ATTACHMENT0; |
mask = GL_COLOR_BUFFER_BIT; |
_mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); |
_mesa_ReadBuffer(GL_COLOR_ATTACHMENT0); |
} |
|
_mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, attachment, |
src_view_tex_image, src_z); |
|
status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER); |
if (status != GL_FRAMEBUFFER_COMPLETE) |
goto meta_end; |
|
_mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, attachment, |
dst_tex_image, dst_z); |
|
status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); |
if (status != GL_FRAMEBUFFER_COMPLETE) |
goto meta_end; |
|
/* Since we've bound a new draw framebuffer, we need to update its |
* derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to |
* be correct. |
*/ |
_mesa_update_state(ctx); |
|
/* We skip the core BlitFramebuffer checks for format consistency. |
* We have already created views to ensure that the texture formats |
* match. |
*/ |
ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, |
src_x, src_y, |
src_x + src_width, src_y + src_height, |
dst_x, dst_y, |
dst_x + src_width, dst_y + src_height, |
mask, GL_NEAREST); |
|
success = true; |
|
meta_end: |
_mesa_DeleteFramebuffers(2, fbos); |
_mesa_meta_end(ctx); |
|
cleanup: |
_mesa_DeleteTextures(1, &src_view_texture); |
|
return success; |
} |