Hash :
218cf9ee
Author :
Date :
2016-05-20T13:55:24
Fix unpacking overlapping unpack buffer rows on NVIDIA GL When unpack parameters are set so that rows being read overlap in the unpack buffer stored in GPU memory, NVIDIA GL driver may not upload the last pixels of the last one or more rows of a texture. The driver may also crash when the amount of overlap is high. This issue affects both TexImage* and TexSubImage* calls. Work around the issue by uploading textures row by row when the rows being read overlap in the unpack buffer. The workaround could possibly be optimized by uploading several of the first rows with a single call in some cases where the amount of overlap is low, but this is expected to be a rarely used corner case, so the added complexity that the optimization would create seems like a bad tradeoff. The issue does not seem to be triggered when the layers (images) of a 3D texture overlap, as long as the rows inside the images don't. The workaround has been ported from Chromium. This patch adds setting dirty bits when unpack state is set in StateManagerGL. The included test case also reveals some issue in the D3D backend, but this is left to be addressed later. BUG=angleproject:1376 TEST=angle_end2end_tests Change-Id: I7dbe73ebb70bbbc284fa92381546f4f2f832d333 Reviewed-on: https://chromium-review.googlesource.com/346430 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureGL.h: Defines the class interface for TextureGL.
#ifndef LIBANGLE_RENDERER_GL_TEXTUREGL_H_
#define LIBANGLE_RENDERER_GL_TEXTUREGL_H_
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/TextureImpl.h"
#include "libANGLE/Texture.h"
namespace rx
{
class BlitGL;
class FunctionsGL;
class StateManagerGL;
struct WorkaroundsGL;
struct LUMAWorkaroundGL
{
bool enabled;
GLenum workaroundFormat;
LUMAWorkaroundGL();
LUMAWorkaroundGL(bool enabled, GLenum workaroundFormat);
};
// Structure containing information about format and workarounds for each mip level of the
// TextureGL.
struct LevelInfoGL
{
// Format of the data used in this mip level.
GLenum sourceFormat;
// If this mip level requires sampler-state re-writing so that only a red channel is exposed.
bool depthStencilWorkaround;
// Information about luminance alpha texture workarounds in the core profile.
LUMAWorkaroundGL lumaWorkaround;
LevelInfoGL();
LevelInfoGL(GLenum sourceFormat,
bool depthStencilWorkaround,
const LUMAWorkaroundGL &lumaWorkaround);
};
class TextureGL : public TextureImpl
{
public:
TextureGL(const gl::TextureState &state,
const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
StateManagerGL *stateManager,
BlitGL *blitter);
~TextureGL() override;
gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
const gl::Framebuffer *source) override;
gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
gl::Error setImageExternal(GLenum target,
egl::Stream *stream,
const egl::Stream::GLTextureDescription &desc) override;
gl::Error generateMipmap() override;
void bindTexImage(egl::Surface *surface) override;
void releaseTexImage() override;
gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
void syncState(size_t textureUnit) const;
GLuint getTextureID() const;
gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
FramebufferAttachmentRenderTarget **rtOut) override
{
return gl::Error(GL_OUT_OF_MEMORY, "Not supported on OpenGL");
}
void setBaseLevel(GLuint) override {}
private:
void setImageHelper(GLenum target,
size_t level,
GLenum internalFormat,
const gl::Extents &size,
GLenum format,
GLenum type,
const uint8_t *pixels);
void reserveTexImageToBeFilled(GLenum target,
size_t level,
GLenum internalFormat,
const gl::Extents &size,
GLenum format,
GLenum type);
gl::Error setSubImageRowByRowWorkaround(GLenum target,
size_t level,
const gl::Box &area,
GLenum format,
GLenum type,
const gl::PixelUnpackState &unpack,
const uint8_t *pixels);
const FunctionsGL *mFunctions;
const WorkaroundsGL &mWorkarounds;
StateManagerGL *mStateManager;
BlitGL *mBlitter;
std::vector<LevelInfoGL> mLevelInfo;
mutable gl::TextureState mAppliedTextureState;
GLuint mTextureID;
};
}
#endif // LIBANGLE_RENDERER_GL_TEXTUREGL_H_