1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #import "GlassOffscreen.h" 27 28 #import "GlassFrameBufferObject.h" 29 //#import "GlassPBuffer.h" 30 31 //#define VERBOSE 32 #ifndef VERBOSE 33 #define LOG(MSG, ...) 34 #else 35 #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__); 36 #endif 37 38 @interface GlassOffscreen () 39 - (void)setContext; 40 - (void)unsetContext; 41 @end 42 43 @implementation GlassOffscreen 44 45 - (id)initWithContext:(CGLContextObj)ctx 46 { 47 self = [super init]; 48 if (self != nil) 49 { 50 self->_ctx = CGLRetainContext(ctx); 51 52 self->_backgroundR = 1.0f; 53 self->_backgroundG = 1.0f; 54 self->_backgroundB = 1.0f; 55 self->_backgroundA = 1.0f; 56 57 [self setContext]; 58 { 59 self->_offscreen = [[GlassFrameBufferObject alloc] init]; 60 if (self->_offscreen == nil) 61 { 62 // TODO: implement PBuffer if needed 63 //self->_offscreen = [[GlassPBuffer alloc] init]; 64 } 65 } 66 [self unsetContext]; 67 } 68 return self; 69 } 70 71 - (CGLContextObj)getContext; 72 { 73 return self->_ctx; 74 } 75 76 - (void)dealloc 77 { 78 [self setContext]; 79 { 80 [(NSObject*)self->_offscreen release]; 81 self->_offscreen = NULL; 82 } 83 [self unsetContext]; 84 85 CGLReleaseContext(self->_ctx); 86 self->_ctx = NULL; 87 88 [super dealloc]; 89 } 90 91 - (void)setBackgroundColor:(NSColor*)color 92 { 93 self->_backgroundR = (GLfloat)[color redComponent]; 94 self->_backgroundG = (GLfloat)[color greenComponent]; 95 self->_backgroundB = (GLfloat)[color blueComponent]; 96 self->_backgroundA = (GLfloat)[color alphaComponent]; 97 } 98 99 - (GLuint)width 100 { 101 return [self->_offscreen width]; 102 } 103 104 - (GLuint)height 105 { 106 return [self->_offscreen height]; 107 } 108 109 - (GLuint)fbo 110 { 111 return [self->_offscreen fbo]; 112 } 113 114 - (CAOpenGLLayer*)getLayer 115 { 116 return _layer; 117 } 118 119 - (void)setLayer:(CAOpenGLLayer*)new_layer 120 { 121 //Set a weak reference as layer owns offscreen 122 self->_layer = new_layer; 123 } 124 125 - (void)setContext 126 { 127 self->_ctxToRestore = CGLGetCurrentContext(); 128 CGLLockContext(self->_ctx); 129 CGLSetCurrentContext(self->_ctx); 130 } 131 132 - (void)unsetContext 133 { 134 CGLSetCurrentContext(self->_ctxToRestore); 135 CGLUnlockContext(self->_ctx); 136 } 137 138 - (void)bindForWidth:(GLuint)width andHeight:(GLuint)height 139 { 140 [self setContext]; 141 [self->_offscreen bindForWidth:width andHeight:height]; 142 [self unsetContext]; 143 } 144 145 - (void)blit 146 { 147 [self blitForWidth:[self->_offscreen width] andHeight:[self->_offscreen height]]; 148 } 149 150 - (GLuint)texture 151 { 152 return [self->_offscreen texture]; 153 } 154 155 - (void)blitForWidth:(GLuint)width andHeight:(GLuint)height 156 { 157 { 158 #if 1 159 glClearColor(self->_backgroundR, self->_backgroundG, self->_backgroundB, self->_backgroundA); 160 glClear(GL_COLOR_BUFFER_BIT); 161 #else 162 // for debugging, change clear color every 0.5 seconds 163 static int counterFps = 0; 164 static int counterColor = 0; 165 counterFps++; 166 if ((counterFps%(60/2)) == 0) 167 { 168 counterColor++; 169 } 170 switch (counterColor%3) 171 { 172 case 0: 173 glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 174 break; 175 case 1: 176 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 177 break; 178 case 2: 179 glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 180 break; 181 } 182 glClear(GL_COLOR_BUFFER_BIT); 183 #endif 184 [self->_offscreen blitForWidth:width andHeight:height]; 185 186 self->_dirty = GL_FALSE; 187 } 188 } 189 190 - (GLboolean)isDirty 191 { 192 return self->_dirty; 193 } 194 195 - (void)blitFromOffscreen:(GlassOffscreen*) other_offscreen 196 { 197 [self setContext]; 198 { 199 [(GlassFrameBufferObject*)self->_offscreen blitFromFBO:(GlassFrameBufferObject*)other_offscreen->_offscreen]; 200 self->_dirty = GL_TRUE; 201 } 202 [self unsetContext]; 203 } 204 205 @end