native-glass.mac.GlassFrameBufferObject.m Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openjfx-78-backport-native Show documentation
Show all versions of openjfx-78-backport-native Show documentation
This contains the native files for the backport of OpenJFX 8 to run on Java 7.
The newest version!
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#import "GlassFrameBufferObject.h"
#import "GlassMacros.h"
#import
#define TARGET GL_TEXTURE_RECTANGLE_EXT
#define FORMAT GL_BGRA
#define TYPE GL_UNSIGNED_INT_8_8_8_8_REV
//#define VERBOSE
#ifndef VERBOSE
#define LOG(MSG, ...)
#else
#define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
#endif
@implementation GlassFrameBufferObject
- (CGLContextObj)_assertContext
{
CGLContextObj cgl_ctx = CGLGetCurrentContext();
assert(cgl_ctx != NULL);
return cgl_ctx;
}
- (BOOL)_supportsFbo
{
return (gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object", glGetString(GL_EXTENSIONS)) == GL_TRUE);
}
- (BOOL)_checkFbo
{
BOOL ok = NO;
{
switch (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
ok = YES;
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
NSLog(@"GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
NSLog(@"GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
NSLog(@"GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
NSLog(@"GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
NSLog(@"GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
NSLog(@"GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
NSLog(@"GL_FRAMEBUFFER_UNSUPPORTED_EXT");
break;
default:
NSLog(@"Unknown FBO Error");
break;
}
}
return ok;
}
- (void)_destroyFbo
{
if (self->_texture != 0)
{
glDeleteTextures(1, &self->_texture);
self->_texture = 0;
}
if (self->_fbo != 0)
{
glDeleteFramebuffersEXT(1, &self->_fbo);
self->_fbo = 0;
}
}
- (void)_createFboIfNeededForWidth:(GLuint)width andHeight:(GLuint)height
{
if ((self->_width != width) || (self->_height != height))
{
// TODO optimization: is it possible to just resize an FBO's texture without destroying it first?
[self _destroyFbo];
}
if (self->_fbo == 0)
{
glEnable(TARGET);
{
glActiveTextureARB(GL_TEXTURE0);
glGenTextures(1, &self->_texture);
LOG(" GlassFrameBufferObject created Texture: %d", self->_texture);
glBindTexture(TARGET, self->_texture);
glTexParameteri(TARGET, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(TARGET, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
{
GLenum target = TARGET;
GLint level = 0;
GLint internalformat = GL_RGBA;
GLint border = 0;
GLenum format = FORMAT;
GLenum type = TYPE;
const GLvoid *pixels = NULL;
glTexImage2D(target, level, internalformat, (GLint)width, (GLint)height, border, format, type, pixels);
}
glGenFramebuffersEXT(1, &self->_fbo);
LOG(" GlassFrameBufferObject created FBO: %d", self->_fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, self->_fbo);
{
GLenum target = GL_FRAMEBUFFER_EXT;
GLenum attachment = GL_COLOR_ATTACHMENT0_EXT;
GLenum textarget = TARGET;
GLuint texture = self->_texture;
GLint level = 0;
glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
}
LOG(" glGetError(): %d", glGetError());
if ([self _checkFbo] == NO)
{
[self _destroyFbo];
}
}
glDisable(TARGET);
glViewport(0, 0, (GLint)width, (GLint)height);
}
// DOES NOT WORK
// else if ((self->_width != width) || (self->_height != height))
// {
// glEnable(TARGET);
// glBindTexture(TARGET, self->_texture);
//
// GLenum target = TARGET;
// GLint level = 0;
// GLint xoffset = 0;
// GLint yoffset = 0;
// GLenum format = FORMAT;
// GLenum type = TYPE;
// const GLvoid *pixels = NULL;
// glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
//
// glDisable(TARGET);
// }
self->_width = width;
self->_height = height;
}
- (id)init
{
self = [super init];
if (self != nil)
{
self->_width = 0;
self->_height = 0;
self->_texture = 0;
self->_fbo = 0;
[self _assertContext];
if ([self _supportsFbo] == NO)
{
[super dealloc];
self = nil;
}
}
return self;
}
- (void)dealloc
{
[self _assertContext];
{
[self _destroyFbo];
}
[super dealloc];
}
- (GLuint)width
{
return self->_width;
}
- (GLuint)height
{
return self->_height;
}
- (void)bindForWidth:(GLuint)width andHeight:(GLuint)height
{
LOG(" GlassFrameBufferObject bindForWidth:%d andHeight:%d", width, height);
LOG(" context:%p", CGLGetCurrentContext());
[self _assertContext];
{
if ((width > 0) && (height > 0))
{
self->_fboToRestore = 0; // default to screen
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, (GLint*)&self->_fboToRestore);
LOG(" will need to restore to FBO: %d", self->_fboToRestore);
[self _createFboIfNeededForWidth:width andHeight:height];
if (self->_fbo != 0)
{
GLuint framebufferToBind = self->_fbo; // our own FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferToBind);
LOG(" bounded to FBO: %d", self->_fbo);
}
}
}
LOG(" BOUND");
LOG(" glGetError(): %d", glGetError());
}
- (void)unbind
{
LOG(" GlassFrameBufferObject unbind");
[self _assertContext];
{
GLint framebufferCurrent = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &framebufferCurrent);
#if 0
assert(framebufferCurrent == self->_fbo);
#else
if ((GLuint)framebufferCurrent != self->_fbo)
{
fprintf(stderr, "ERROR: unexpected fbo is bound! Expected %d, but found %d\n", self->_fbo, framebufferCurrent);
}
#endif
GLuint framebufferToRevertTo = self->_fboToRestore;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferToRevertTo);
LOG(" restored to FBO: %d", framebufferToRevertTo);
LOG(" glGetError(): %d", glGetError());
}
}
- (void)blitForWidth:(GLuint)width andHeight:(GLuint)height
{
LOG(" GlassFrameBufferObject blitForWidth:%d andHeight:%d [%p]", width, height, self);
if (self->_texture != 0)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(TARGET);
{
glActiveTextureARB(GL_TEXTURE0);
glBindTexture(TARGET, self->_texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
{
glBegin(GL_QUADS);
{
glTexCoord2f( 0.0f, self->_height); glVertex2f( 0.0f, 0.0f);
glTexCoord2f(self->_width, self->_height); glVertex2f(self->_width, 0.0f);
glTexCoord2f(self->_width, 0.0f); glVertex2f(self->_width, self->_height);
glTexCoord2f( 0.0f, 0.0f); glVertex2f( 0.0f, self->_height);
}
glEnd();
}
glBindTexture(TARGET, 0);
}
glDisable(TARGET);
LOG(" BLITED");
LOG(" glGetError(): %d", glGetError());
}
}
- (GLuint)texture
{
return self->_texture;
}
- (GLuint)fbo
{
return self->_fbo;
}
@end