RSS

(root)/iphone/common : /source/GLESView.m (revision 61)

To get this branch, use:
bzr branch /browse/iphone/common
Line Revision Contents
1 12
//
2
//  GLESView.m
3
//  MarineCompass
4
//
5
//  Created by döme on 03.08.2009.
6
//
7
8 54
/*
9
 * Copyright (c) 2009 Doemoetoer Gulyas.
10
 * All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in the
19
 *    documentation and/or other materials provided with the distribution.
20
 * 3. The name of the author may not be used to endorse or promote products
21
 *    derived from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
 */
34
35
36 12
#import "GLESView.h"
37
38
#import <QuartzCore/QuartzCore.h>
39
#import <OpenGLES/EAGLDrawable.h>
40
#import <CoreGraphics/CoreGraphics.h>
41
42
#import "geometry.h"
43
#import "VertexArray.h"
44 20
#import "ESShader.h"
45
46
47
@interface ESShader (GLESView)
48
+ (void) setShaderAPI: (EAGLRenderingAPI) api;
49
@end
50
51 12
52
@implementation GLESView
53
54 13
+ (Class)layerClass
55
{
56 12
    return [CAEAGLLayer class];
57
}
58
59 17
- (void) lineGradientTexture: (GLuint*) texname red: (float) r green: (float) g blue: (float) b
60
{
61
	uint8_t* spriteData = calloc(1, 256 * 4);
62 29
	for (int i = 0; i < 256; ++i)
63 17
	{
64
		spriteData[4*i+0] = r*(float)i;
65
		spriteData[4*i+1] = g*(float)i;
66
		spriteData[4*i+2] = b*(float)i;
67
		spriteData[4*i+3] = i;
68
	}
69
70
	glGenTextures(1, texname);
71
	glBindTexture(GL_TEXTURE_2D, *texname);
72
73
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
74
75
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
76
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
77
78
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
79
80
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
81
82
	free(spriteData);
83
}
84
85 29
- (void) doubleGradientTexture: (GLuint*) texname red: (float) r green: (float) g blue: (float) b
86
{
87
	uint8_t* spriteData = calloc(1, 512 * 4);
88
	for (int i = 0; i < 256; ++i)
89
	{
90
		spriteData[4*i+0] = r*(float)i;
91
		spriteData[4*i+1] = g*(float)i;
92
		spriteData[4*i+2] = b*(float)i;
93
		spriteData[4*i+3] = i;
94
	}
95
	
96
	for (int i = 256; i < 512; ++i)
97
	{
98
		spriteData[4*i+0] = r*(float)(511-i);
99
		spriteData[4*i+1] = g*(float)(511-i);
100
		spriteData[4*i+2] = b*(float)(511-i);
101
		spriteData[4*i+3] = (511-i);
102
	}
103
104
105
	glGenTextures(1, texname);
106
	glBindTexture(GL_TEXTURE_2D, *texname);
107
108
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
109
110
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
111
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
112
113
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
114
115
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
116
117
	free(spriteData);
118
}
119
120
121 17
- (void) textureFromCgImage: (CGImageRef) img texName: (GLuint*) texname width: (size_t) width height: (size_t) height repeat: (BOOL) doRepeat mipmap: (BOOL) doMipmap filter: (BOOL) doFilter
122 13
{
123
	void* spriteData = malloc(width * height * 4);
124 23
	
125
	assert(img);
126
127
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
128
	CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast);
129
	CGColorSpaceRelease(colorSpace);
130
131 13
	CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), img);
132
	CGContextRelease(spriteContext);
133
	
134
	glGenTextures(1, texname);
135
	glBindTexture(GL_TEXTURE_2D, *texname);
136
137
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
138
139
	free(spriteData);
140
141
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, doRepeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
142
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, doRepeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
143
144
	if (doMipmap)
145
		glGenerateMipmap(GL_TEXTURE_2D);
146 17
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, doFilter ? (doMipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) : GL_NEAREST);
147 13
148 17
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, doFilter ? GL_LINEAR : GL_NEAREST);
149 13
}
150
151 23
- (void) loadTextureFromBitmapNamed: (NSString*) name texName: (GLuint*) texname repeat: (BOOL) doRepeat mipmap: (BOOL) doMipmap filter: (BOOL) doFilter
152 12
{
153
154
	// Creates a Core Graphics image from an image file
155 13
	CGImageRef spriteImage = [UIImage imageNamed: name].CGImage;
156 12
	// Get the width and height of the image
157 13
	size_t width = CGImageGetWidth(spriteImage);
158
	size_t height = CGImageGetHeight(spriteImage);
159
160
161 17
	[self textureFromCgImage: spriteImage texName: texname width: width height: height repeat: doRepeat mipmap: doMipmap filter: doFilter];
162 13
	
163 12
}
164
165 23
static CGImageRef	CreateCGImageFromPDFPage(CGPDFDocumentRef document, size_t pageNumber, int width, int height)
166
{
167
168
	CGPDFPageRef page = CGPDFDocumentGetPage(document, pageNumber);
169
	if(!page)
170
		return NULL;
171
172
//	CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
173
174
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
175
//	void* data = malloc(4*width*height);
176
	CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast);
177
	CGColorSpaceRelease(colorSpace);
178
179
	if(!bitmapContext)
180
	{
181
		//free(data);
182
		return NULL;
183
	}
184
185
	CGAffineTransform M = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, CGRectMake(0.0f, 0.0f, width, height), 0, NO);
186
	
187
	CGContextConcatCTM(bitmapContext, M);
188
	CGContextDrawPDFPage(bitmapContext, page);									
189
	CGImageRef pdfImage = CGBitmapContextCreateImage(bitmapContext);
190
	CFRelease(bitmapContext);
191
	//free(data);
192
	return pdfImage;  
193
194
} 
195
196
static CGImageRef CreateImageFromPDFNamed(NSString* name, int width, int height)
197
{
198
	CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef) [[NSBundle mainBundle] pathForResource: name ofType: nil], 0, NO);
199
	CGPDFDocumentRef pdfDoc = CGPDFDocumentCreateWithURL(url);
200
	CFRelease(url);
201
	assert(pdfDoc);
202
	
203
	CGImageRef img = CreateCGImageFromPDFPage(pdfDoc, 1, width, height);
204
	
205
	CGPDFDocumentRelease(pdfDoc);
206
	
207
	return img;
208
}
209
210
211
- (void) loadTextureFromPDFNamed: (NSString*) name texName: (GLuint*) texname width: (size_t) width height: (size_t) height repeat: (BOOL) doRepeat mipmap: (BOOL) doMipmap filter: (BOOL) doFilter
212
{
213
214
	CGImageRef img = CreateImageFromPDFNamed(name, width, height);
215
	[self textureFromCgImage: img texName: texname width: width height: height repeat: doRepeat mipmap: doMipmap filter: doFilter];
216
	CGImageRelease(img);
217
}
218
219 12
220
//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
221
- (id)initWithCoder:(NSCoder*)coder {
222
    
223
    if (!(self = [super initWithCoder:coder]))
224
		return nil;
225
226
	CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
227
	
228
	eaglLayer.opaque = YES;
229
	eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
230
	
231 21
	context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
232
	if (!context)
233
		context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
234 12
	
235 20
	if (!context || ![EAGLContext setCurrentContext: context])
236
	{
237 12
		[self release];
238
		return nil;
239
	}
240
	
241 20
	animationInterval = 1.0 / 100.0;
242 21
		
243
	[self setupGraphicsForApi: [context API]];
244 12
245
    return self;
246
}
247
248 51
- (id)initWithFrame:(CGRect)frame {
249
    
250
    if (!(self = [super initWithFrame:frame]))
251
		return nil;
252
253
	CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
254
	
255
	eaglLayer.opaque = YES;
256
	eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
257
	
258
	context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
259
	if (!context)
260
		context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
261
	
262
	if (!context || ![EAGLContext setCurrentContext: context])
263
	{
264
		[self release];
265
		return nil;
266
	}
267
	
268
	animationInterval = 1.0 / 100.0;
269
		
270
	[self setupGraphicsForApi: [context API]];
271
272
    return self;
273
}
274
275
276
277 12
- (void) setupGraphicsForApi: (EAGLRenderingAPI) glApi
278
{
279
	glClearColor(0.0,0.0,1.0,1.0);
280
}
281
282
283
- (void)dealloc 
284
{
285
    [self stopAnimation];
286
    
287
    if ([EAGLContext currentContext] == context)
288
        [EAGLContext setCurrentContext:nil];
289
    
290
    [context release];  
291
    [super dealloc];
292
}
293
294
295
- (void) setupViewDrawing
296
{
297
    [EAGLContext setCurrentContext:context];
298
    
299
    glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
300
    glViewport(0, 0, backingWidth, backingHeight);
301
302
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
303
}
304
305
- (void) finishViewDrawing
306
{
307
	glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
308
    [context presentRenderbuffer: GL_RENDERBUFFER];
309 36
	
310
	GLenum err = glGetError();
311
	if (err)
312
		NSLog(@"OpenGL error %d occured", err);
313 12
}
314
315
- (void) drawView
316
{
317
	[self setupViewDrawing];
318
	
319
	[self finishViewDrawing];
320
}
321
322
323
- (void)drawRect:(CGRect)rect
324
{
325
	[super drawRect: rect];
326
	
327
	[self drawView];
328
329
//	[[UIColor clearColor] set];
330
//	UIRectFill(rect);
331
}
332
333
- (void)animationCallback
334
{
335
336
}
337
338
339
- (void)startAnimation
340
{
341
    animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(animationCallback) userInfo:nil repeats:YES];
342
}
343
344
345
- (void)stopAnimation
346
{
347
    animationTimer = nil;
348
}
349
350
351
- (void)setAnimationTimer:(NSTimer *)newTimer
352
{
353
    [animationTimer invalidate];
354
    animationTimer = newTimer;
355
}
356
357
358
- (void)setAnimationInterval:(NSTimeInterval)interval
359
{
360
    
361
    animationInterval = interval;
362
    if (animationTimer) {
363
        [self stopAnimation];
364
        [self startAnimation];
365
    }
366
}
367
368
369
370
- (BOOL)createFramebuffer {
371
    
372
    glGenFramebuffers(1, &viewFramebuffer);
373
    glGenRenderbuffers(1, &viewRenderbuffer);
374
    
375
    glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
376
    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
377
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
378
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
379
    
380
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
381
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
382
    
383
    if (USE_DEPTH_BUFFER) {
384
        glGenRenderbuffers(1, &depthRenderbuffer);
385
        glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
386
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
387
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
388
    }
389
    
390 38
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
391
	{
392 12
        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
393 38
		NSLog(@"%f %f %f %f", self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
394 12
        return NO;
395
    }
396
    
397
    return YES;
398
}
399
400
401
- (void)destroyFramebuffer {
402
    
403
    glDeleteFramebuffers(1, &viewFramebuffer);
404
    viewFramebuffer = 0;
405
    glDeleteRenderbuffers(1, &viewRenderbuffer);
406
    viewRenderbuffer = 0;
407
    
408
    if(depthRenderbuffer)
409
	{
410
        glDeleteRenderbuffers(1, &depthRenderbuffer);
411
        depthRenderbuffer = 0;
412
    }
413
}
414
415
- (void)layoutSubviews {
416
    [EAGLContext setCurrentContext:context];
417
    [self destroyFramebuffer];
418
    [self createFramebuffer];
419
    [self drawView];
420
}
421
422
@synthesize animationInterval;
423
424
@end

Loggerhead 1.17 is a web-based interface for Bazaar branches