mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Improved some openGL texture creation functionality.
This commit is contained in:
parent
fe3a2e4495
commit
e75663b467
8 changed files with 97 additions and 85 deletions
|
|
@ -47,6 +47,7 @@ Graphics::Graphics (const Image& imageToDrawOnto)
|
|||
contextToDelete (&context),
|
||||
saveStatePending (false)
|
||||
{
|
||||
jassert (imageToDrawOnto.isValid()); // Can't draw into a null image!
|
||||
}
|
||||
|
||||
Graphics::Graphics (LowLevelGraphicsContext* const internalContext) noexcept
|
||||
|
|
|
|||
|
|
@ -159,6 +159,28 @@ static void clearGLError()
|
|||
while (glGetError() != GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
struct OpenGLTargetSaver
|
||||
{
|
||||
OpenGLTargetSaver (const OpenGLContext& c)
|
||||
: context (c), oldFramebuffer (OpenGLFrameBuffer::getCurrentFrameBufferTarget())
|
||||
{
|
||||
glGetIntegerv (GL_VIEWPORT, oldViewport);
|
||||
}
|
||||
|
||||
~OpenGLTargetSaver()
|
||||
{
|
||||
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, oldFramebuffer);
|
||||
glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
||||
}
|
||||
|
||||
private:
|
||||
const OpenGLContext& context;
|
||||
GLuint oldFramebuffer;
|
||||
GLint oldViewport[4];
|
||||
|
||||
OpenGLTargetSaver& operator= (const OpenGLTargetSaver&);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#include "opengl/juce_OpenGLFrameBuffer.cpp"
|
||||
#include "opengl/juce_OpenGLGraphicsContext.cpp"
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ public:
|
|||
glBindTexture (GL_TEXTURE_2D, cachedImageFrameBuffer.getTextureID());
|
||||
|
||||
const Rectangle<int> cacheBounds (cachedImageFrameBuffer.getWidth(), cachedImageFrameBuffer.getHeight());
|
||||
context.copyTexture (cacheBounds, cacheBounds, cacheBounds.getWidth(), cacheBounds.getHeight());
|
||||
context.copyTexture (cacheBounds, cacheBounds, cacheBounds.getWidth(), cacheBounds.getHeight(), false);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
|
@ -672,7 +672,8 @@ void OpenGLContext::setAssociatedObject (const char* name, ReferenceCountedObjec
|
|||
|
||||
void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
||||
const Rectangle<int>& anchorPosAndTextureSize,
|
||||
const int contextWidth, const int contextHeight)
|
||||
const int contextWidth, const int contextHeight,
|
||||
bool flippedVertically)
|
||||
{
|
||||
if (contextWidth <= 0 || contextHeight <= 0)
|
||||
return;
|
||||
|
|
@ -722,12 +723,13 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
|||
|
||||
prog.addShader ("uniform sampler2D imageTexture;"
|
||||
"uniform " JUCE_HIGHP " float textureBounds[4];"
|
||||
"uniform " JUCE_HIGHP " vec2 vOffsetAndScale;"
|
||||
"varying " JUCE_HIGHP " vec2 pixelPos;"
|
||||
"void main()"
|
||||
"{"
|
||||
JUCE_HIGHP " vec2 texturePos = (pixelPos - vec2 (textureBounds[0], textureBounds[1]))"
|
||||
"/ vec2 (textureBounds[2], textureBounds[3]);"
|
||||
"gl_FragColor = texture2D (imageTexture, vec2 (texturePos.x, 1.0 - texturePos.y));"
|
||||
"gl_FragColor = texture2D (imageTexture, vec2 (texturePos.x, vOffsetAndScale.x + vOffsetAndScale.y * texturePos.y));"
|
||||
"}",
|
||||
GL_FRAGMENT_SHADER);
|
||||
prog.link();
|
||||
|
|
@ -740,19 +742,23 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
|||
: positionAttribute (prog, "position"),
|
||||
screenSize (prog, "screenSize"),
|
||||
imageTexture (prog, "imageTexture"),
|
||||
textureBounds (prog, "textureBounds")
|
||||
textureBounds (prog, "textureBounds"),
|
||||
vOffsetAndScale (prog, "vOffsetAndScale")
|
||||
{}
|
||||
|
||||
void set (const float targetWidth, const float targetHeight, const Rectangle<float>& bounds) const
|
||||
void set (const float targetWidth, const float targetHeight, const Rectangle<float>& bounds, bool flippedVertically) const
|
||||
{
|
||||
const GLfloat m[] = { bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight() };
|
||||
textureBounds.set (m, 4);
|
||||
imageTexture.set (0);
|
||||
screenSize.set (targetWidth, targetHeight);
|
||||
|
||||
vOffsetAndScale.set (flippedVertically ? 0.0f : 1.0f,
|
||||
flippedVertically ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
OpenGLShaderProgram::Attribute positionAttribute;
|
||||
OpenGLShaderProgram::Uniform screenSize, imageTexture, textureBounds;
|
||||
OpenGLShaderProgram::Uniform screenSize, imageTexture, textureBounds, vOffsetAndScale;
|
||||
};
|
||||
|
||||
OpenGLShaderProgram program;
|
||||
|
|
@ -767,7 +773,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
|
|||
const GLshort vertices[] = { left, bottom, right, bottom, left, top, right, top };
|
||||
|
||||
const OverlayShaderProgram& program = OverlayShaderProgram::select (*this);
|
||||
program.params.set ((float) contextWidth, (float) contextHeight, anchorPosAndTextureSize.toFloat());
|
||||
program.params.set ((float) contextWidth, (float) contextHeight, anchorPosAndTextureSize.toFloat(), flippedVertically);
|
||||
|
||||
extensions.glVertexAttribPointer (program.params.positionAttribute.attributeID, 2, GL_SHORT, GL_FALSE, 4, vertices);
|
||||
extensions.glEnableVertexAttribArray (program.params.positionAttribute.attributeID);
|
||||
|
|
|
|||
|
|
@ -219,10 +219,13 @@ public:
|
|||
used for scaling of the coordinates.
|
||||
@param contextHeight the height of the context or framebuffer that is being drawn into,
|
||||
used for vertical flipping of the y coordinates.
|
||||
@param textureOriginIsBottomLeft if true, the texture's origin is treated as being at
|
||||
(0, 0). If false, it is assumed to be (0, 1)
|
||||
*/
|
||||
void copyTexture (const Rectangle<int>& targetClipArea,
|
||||
const Rectangle<int>& anchorPosAndTextureSize,
|
||||
int contextWidth, int contextHeight);
|
||||
int contextWidth, int contextHeight,
|
||||
bool textureOriginIsBottomLeft);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ bool OpenGLFrameBuffer::initialise (OpenGLFrameBuffer& other)
|
|||
clearGLError();
|
||||
#endif
|
||||
glBindTexture (GL_TEXTURE_2D, p->textureID);
|
||||
pimpl->context.copyTexture (area, area, area.getWidth(), area.getHeight());
|
||||
pimpl->context.copyTexture (area, area, area.getWidth(), area.getHeight(), false);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
|
||||
|
|
@ -325,13 +325,14 @@ bool OpenGLFrameBuffer::readPixels (PixelARGB* target, const Rectangle<int>& are
|
|||
glReadPixels (area.getX(), area.getY(), area.getWidth(), area.getHeight(),
|
||||
JUCE_RGBA_FORMAT, GL_UNSIGNED_BYTE, target);
|
||||
pimpl->context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
glPixelStorei (GL_PACK_ALIGNMENT, 0);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle<int>& area)
|
||||
{
|
||||
OpenGLTargetSaver ts (pimpl->context);
|
||||
|
||||
if (! makeCurrentRenderingTarget())
|
||||
return false;
|
||||
|
||||
|
|
@ -339,10 +340,10 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle<int>
|
|||
glDisable (GL_BLEND);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
|
||||
#if JUCE_OPENGL_ES && JUCE_USE_OPENGL_FIXED_FUNCTION
|
||||
OpenGLTexture tex;
|
||||
tex.loadARGBFlipped (data, area.getWidth(), area.getHeight());
|
||||
|
||||
#if JUCE_OPENGL_ES && JUCE_USE_OPENGL_FIXED_FUNCTION
|
||||
const int texH = tex.getHeight();
|
||||
tex.bind();
|
||||
const GLint cropRect[4] = { 0, texH - area.getHeight(), area.getWidth(), area.getHeight() };
|
||||
|
|
@ -353,10 +354,15 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle<int>
|
|||
glDrawTexiOES (area.getX(), area.getY(), 1, area.getWidth(), area.getHeight());
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
#else
|
||||
pimpl->context.copyTexture (area, area, pimpl->width, pimpl->height);
|
||||
OpenGLTexture tex;
|
||||
tex.loadARGB (data, area.getWidth(), area.getHeight());
|
||||
|
||||
glViewport (0, 0, pimpl->width, pimpl->height);
|
||||
pimpl->context.copyTexture (area, Rectangle<int> (area.getX(), area.getY(),
|
||||
tex.getWidth(), tex.getHeight()),
|
||||
pimpl->width, pimpl->height, true);
|
||||
#endif
|
||||
|
||||
pimpl->context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1364,7 +1364,7 @@ public:
|
|||
clip (other.clip),
|
||||
maskArea (other.clip)
|
||||
{
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
state.currentShader.clearShader (state.shaderQuadQueue);
|
||||
state.shaderQuadQueue.flush();
|
||||
state.activeTextures.setSingleTextureMode (state.shaderQuadQueue);
|
||||
|
|
@ -1393,7 +1393,7 @@ public:
|
|||
clip (r.getBounds()),
|
||||
maskArea (clip)
|
||||
{
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
state.currentShader.clearShader (state.shaderQuadQueue);
|
||||
state.shaderQuadQueue.flush();
|
||||
state.activeTextures.clear();
|
||||
|
|
@ -1429,7 +1429,7 @@ public:
|
|||
if (excluded.getNumRectangles() == 1)
|
||||
return excludeClipRectangle (excluded.getRectangle (0));
|
||||
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
makeActive();
|
||||
state.blendMode.setBlendMode (state.shaderQuadQueue, true);
|
||||
state.currentShader.setShader (maskArea, state.shaderQuadQueue, state.currentShader.programs->solidColourProgram);
|
||||
|
|
@ -1445,7 +1445,7 @@ public:
|
|||
if (r.contains (clip))
|
||||
return Ptr();
|
||||
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
makeActive();
|
||||
state.blendMode.setBlendMode (state.shaderQuadQueue, true);
|
||||
state.currentShader.setShader (maskArea, state.shaderQuadQueue, state.currentShader.programs->solidColourProgram);
|
||||
|
|
@ -1460,7 +1460,7 @@ public:
|
|||
|
||||
if (! et.isEmpty())
|
||||
{
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
state.currentShader.clearShader (state.shaderQuadQueue);
|
||||
state.shaderQuadQueue.flush();
|
||||
state.activeTextures.clear();
|
||||
|
|
@ -1480,7 +1480,7 @@ public:
|
|||
if (clip.isEmpty())
|
||||
return Ptr();
|
||||
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
makeActive();
|
||||
|
||||
state.activeTextures.setSingleTextureMode (state.shaderQuadQueue);
|
||||
|
|
@ -1501,7 +1501,7 @@ public:
|
|||
|
||||
Ptr clipToImageAlpha (const OpenGLTextureFromImage& image, const AffineTransform& transform)
|
||||
{
|
||||
TargetSaver ts (state.target.context);
|
||||
OpenGLTargetSaver ts (state.target.context);
|
||||
makeActive();
|
||||
state.activeTextures.setSingleTextureMode (state.shaderQuadQueue);
|
||||
state.activeTextures.bindTexture (image.textureID);
|
||||
|
|
@ -1617,28 +1617,6 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE (ShaderFillOperation)
|
||||
};
|
||||
|
||||
struct TargetSaver
|
||||
{
|
||||
TargetSaver (const OpenGLContext& c)
|
||||
: context (c), oldFramebuffer (OpenGLFrameBuffer::getCurrentFrameBufferTarget())
|
||||
{
|
||||
glGetIntegerv (GL_VIEWPORT, oldViewport);
|
||||
}
|
||||
|
||||
~TargetSaver()
|
||||
{
|
||||
context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, oldFramebuffer);
|
||||
glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
||||
}
|
||||
|
||||
private:
|
||||
const OpenGLContext& context;
|
||||
GLuint oldFramebuffer;
|
||||
GLint oldViewport[4];
|
||||
|
||||
TargetSaver& operator= (const TargetSaver&);
|
||||
};
|
||||
|
||||
void makeActive()
|
||||
{
|
||||
state.shaderQuadQueue.flush();
|
||||
|
|
@ -2209,7 +2187,8 @@ public:
|
|||
target.makeActive();
|
||||
target.context.copyTexture (target.bounds, Rectangle<int> (texture.getWidth(),
|
||||
texture.getHeight()),
|
||||
target.bounds.getWidth(), target.bounds.getHeight());
|
||||
target.bounds.getWidth(), target.bounds.getHeight(),
|
||||
false);
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ bool OpenGLTexture::isValidSize (int width, int height)
|
|||
return isPowerOfTwo (width) && isPowerOfTwo (height);
|
||||
}
|
||||
|
||||
void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum type)
|
||||
void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum type, bool topLeft)
|
||||
{
|
||||
ownerContext = OpenGLContext::getCurrentContext();
|
||||
|
||||
|
|
@ -46,11 +46,6 @@ void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum
|
|||
// context. You'll need to create this object in one of the OpenGLContext's callbacks.
|
||||
jassert (ownerContext != nullptr);
|
||||
|
||||
jassert (isValidSize (w, h)); // Perhaps these dimensions must be a power-of-two?
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
if (textureID == 0)
|
||||
{
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
|
|
@ -70,8 +65,26 @@ void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum
|
|||
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, type == GL_ALPHA ? GL_ALPHA : GL_RGBA,
|
||||
w, h, 0, type, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
width = nextPowerOfTwo (w);
|
||||
height = nextPowerOfTwo (h);
|
||||
|
||||
const GLint internalformat = type == GL_ALPHA ? GL_ALPHA : GL_RGBA;
|
||||
|
||||
if (width != w || height != h)
|
||||
{
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, internalformat,
|
||||
width, height, 0, type, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, topLeft ? (height - h) : 0, w, h,
|
||||
type, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, internalformat,
|
||||
w, h, 0, type, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
|
||||
JUCE_CHECK_OPENGL_ERROR
|
||||
}
|
||||
|
||||
|
|
@ -79,29 +92,20 @@ template <class PixelType>
|
|||
struct Flipper
|
||||
{
|
||||
static void flip (HeapBlock<PixelARGB>& dataCopy, const uint8* srcData, const int lineStride,
|
||||
const int w, const int h, const int textureW, const int textureH)
|
||||
const int w, const int h)
|
||||
{
|
||||
dataCopy.malloc ((size_t) (textureW * textureH));
|
||||
dataCopy.malloc ((size_t) (w * h));
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
const PixelType* src = (const PixelType*) srcData;
|
||||
PixelARGB* const dst = (PixelARGB*) (dataCopy + textureW * (textureH - 1 - y));
|
||||
PixelARGB* const dst = (PixelARGB*) (dataCopy + w * (h - 1 - y));
|
||||
|
||||
for (int x = 0; x < w; ++x)
|
||||
dst[x].set (src[x]);
|
||||
|
||||
if (textureW > w)
|
||||
dst[w].set (PixelARGB (0));
|
||||
|
||||
srcData += lineStride;
|
||||
}
|
||||
|
||||
// for textures which are larger than the area of interest, clear the pixels that lie
|
||||
// just outside the actual image, so that the texture interpolation doesn't read junk.
|
||||
if (textureH > h)
|
||||
zeromem (dataCopy + textureW * (textureH - 1 - h),
|
||||
sizeof (PixelARGB) * jmin (textureW, w + 1));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -109,44 +113,37 @@ void OpenGLTexture::loadImage (const Image& image)
|
|||
{
|
||||
const int imageW = image.getWidth();
|
||||
const int imageH = image.getHeight();
|
||||
const int textureW = nextPowerOfTwo (imageW);
|
||||
const int textureH = nextPowerOfTwo (imageH);
|
||||
|
||||
HeapBlock<PixelARGB> dataCopy;
|
||||
Image::BitmapData srcData (image, Image::BitmapData::readOnly);
|
||||
|
||||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB: Flipper<PixelARGB> ::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH, textureW, textureH); break;
|
||||
case Image::RGB: Flipper<PixelRGB> ::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH, textureW, textureH); break;
|
||||
case Image::SingleChannel: Flipper<PixelAlpha>::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH, textureW, textureH); break;
|
||||
case Image::ARGB: Flipper<PixelARGB> ::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH); break;
|
||||
case Image::RGB: Flipper<PixelRGB> ::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH); break;
|
||||
case Image::SingleChannel: Flipper<PixelAlpha>::flip (dataCopy, srcData.data, srcData.lineStride, imageW, imageH); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
create (textureW, textureH, dataCopy, JUCE_RGBA_FORMAT);
|
||||
create (imageW, imageH, dataCopy, JUCE_RGBA_FORMAT, true);
|
||||
}
|
||||
|
||||
void OpenGLTexture::loadARGB (const PixelARGB* pixels, const int w, const int h)
|
||||
{
|
||||
jassert (isValidSize (w, h));
|
||||
create (w, h, pixels, JUCE_RGBA_FORMAT);
|
||||
create (w, h, pixels, JUCE_RGBA_FORMAT, false);
|
||||
}
|
||||
|
||||
void OpenGLTexture::loadAlpha (const uint8* pixels, int w, int h)
|
||||
{
|
||||
jassert (isValidSize (w, h));
|
||||
create (w, h, pixels, GL_ALPHA);
|
||||
create (w, h, pixels, GL_ALPHA, false);
|
||||
}
|
||||
|
||||
void OpenGLTexture::loadARGBFlipped (const PixelARGB* pixels, int w, int h)
|
||||
{
|
||||
const int textureW = nextPowerOfTwo (w);
|
||||
const int textureH = nextPowerOfTwo (h);
|
||||
|
||||
HeapBlock<PixelARGB> flippedCopy;
|
||||
Flipper<PixelARGB>::flip (flippedCopy, (const uint8*) pixels, 4 * w, w, h, textureW, textureH);
|
||||
Flipper<PixelARGB>::flip (flippedCopy, (const uint8*) pixels, 4 * w, w, h);
|
||||
|
||||
loadARGB (flippedCopy, textureW, textureH);
|
||||
create (w, h, flippedCopy, JUCE_RGBA_FORMAT, true);
|
||||
}
|
||||
|
||||
void OpenGLTexture::release()
|
||||
|
|
|
|||
|
|
@ -47,11 +47,10 @@ public:
|
|||
void loadImage (const Image& image);
|
||||
|
||||
/** Creates a texture from a raw array of pixels.
|
||||
The width and height provided must be valid - i.e. power-of-two unless
|
||||
the underlying GL system allows otherwise.
|
||||
If width and height are not powers-of-two, the texture will be created with a
|
||||
larger size, and only the subsection (0, 0, width, height) will be initialised.
|
||||
The data is sent directly to the OpenGL driver without being flipped vertically,
|
||||
so the first pixel will be mapped onto texture coordinate (0, 0).
|
||||
bottom-left corner of the texture
|
||||
*/
|
||||
void loadARGB (const PixelARGB* pixels, int width, int height);
|
||||
|
||||
|
|
@ -63,11 +62,10 @@ public:
|
|||
void loadARGBFlipped (const PixelARGB* pixels, int width, int height);
|
||||
|
||||
/** Creates an alpha-channel texture from an array of alpha values.
|
||||
The width and height provided must be valid - i.e. power-of-two unless
|
||||
the underlying GL system allows otherwise.
|
||||
If width and height are not powers-of-two, the texture will be created with a
|
||||
larger size, and only the subsection (0, 0, width, height) will be initialised.
|
||||
The data is sent directly to the OpenGL driver without being flipped vertically,
|
||||
so the first pixel will be mapped onto texture coordinate (0, 0).
|
||||
bottom-left corner of the texture
|
||||
*/
|
||||
void loadAlpha (const uint8* pixels, int width, int height);
|
||||
|
||||
|
|
@ -112,7 +110,7 @@ private:
|
|||
int width, height;
|
||||
OpenGLContext* ownerContext;
|
||||
|
||||
void create (int w, int h, const void*, GLenum type);
|
||||
void create (int w, int h, const void*, GLenum, bool topLeft);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLTexture)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue