summaryrefslogtreecommitdiff
path: root/src/powdertoyjava/OpenGLCanvasMacOS.mm
blob: c169c5f39498759ff09545a1542ee23e900ebd67 (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#ifdef USE_JNI
#include "OpenGLCanvasMacOS.h"

static jfieldID ctxID = NULL;

NSOpenGLPixelFormat* defaultPixelFormat()
{
    NSOpenGLPixelFormatAttribute attributes [] = {
        NSOpenGLPFAWindow,
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16,
        0
    };
    return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
}

NSOpenGLContext* ensureContext(NSOpenGLContext* openGLContext, NSView *view) {
	NSOpenGLContext* _openGLContext = openGLContext;
	if (!_openGLContext) {
		NSOpenGLPixelFormat* pixelFormat = defaultPixelFormat();
        _openGLContext = [[NSOpenGLContext alloc] 
						  initWithFormat:pixelFormat
						  shareContext:nil];
		[pixelFormat release];
	}
	if ([_openGLContext view] != view) {
		[_openGLContext setView:view];
	}
	[_openGLContext makeCurrentContext];
	
	return _openGLContext;
}

ContextInfo* getContext(JNIEnv *env, jobject canvas) 
{
	if (!ctxID) {
		jclass cls = env->GetObjectClass(canvas);
		ctxID = env->GetFieldID(cls, "openGLContext", "J");
	}	
	
	ContextInfo *ci = (ContextInfo *)(long)(env->GetLongField(canvas, ctxID));
	
	if (!ci) {
		ci = (ContextInfo *)calloc(sizeof(ContextInfo), 1);
		ci->awt = (JAWT *)calloc(sizeof(JAWT), 1);
		env->SetLongField(canvas, ctxID, (jlong)(long)ci);
	}
	
	return ci;
}

void freeContext(JNIEnv *env, jobject canvas, ContextInfo* ci) 
{
	if (ci) {
		free(ci->awt);
		free(ci);
		env->SetLongField(canvas, ctxID, 0L);
	}
}

JNIEXPORT jboolean JNICALL Java_OpenGLCanvas_beginOpenGL(JNIEnv *env, jobject canvas)
{
	ContextInfo *ci = getContext(env, canvas);
	
    // Lock the drawing surface
    // You must lock EACH TIME before drawing
    jint lock = ci->ds->Lock(ci->ds); 
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
    }
    assert((lock & JAWT_LOCK_ERROR) == 0);
    
    // Get the drawing surface info
    ci->dsi = ci->ds->GetDrawingSurfaceInfo(ci->ds);
	
	// Check DrawingSurfaceInfo.  This can be NULL on Mac OS X
    // if the windowing system is not ready
	if (ci->dsi != NULL) {
        // Get the platform-specific drawing info
        // We will use this to get at Cocoa and CoreGraphics
        // See <JavaVM/jawt_md.h>
        ci->dsi_mac = (JAWT_MacOSXDrawingSurfaceInfo*)ci->dsi->platformInfo;
        if (env->ExceptionOccurred()) {
            env->ExceptionDescribe();
        }
		
        // Get the corresponding peer from the caller canvas
        ci->view = ci->dsi_mac->cocoaViewRef;
		ci->openGLContext = ensureContext(ci->openGLContext, ci->view);
		
		return JNI_TRUE;
	}
	
	return JNI_FALSE;
}

JNIEXPORT void JNICALL Java_OpenGLCanvas_endOpenGL(JNIEnv *env, jobject canvas)
{
	ContextInfo *ci = getContext(env, canvas);
	
	[ci->openGLContext flushBuffer];
	
	// Free the DrawingSurfaceInfo
	ci->ds->FreeDrawingSurfaceInfo(ci->dsi);
	if (env->ExceptionOccurred()){
		env->ExceptionDescribe();
	}
	
    // Unlock the drawing surface
    // You must unlock EACH TIME when done drawing
    ci->ds->Unlock(ci->ds); 
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
    }
}

JNIEXPORT void JNICALL Java_OpenGLCanvas_updateOpenGL(JNIEnv *env, jobject canvas)
{
	ContextInfo *ci = getContext(env, canvas);
	
	[ci->openGLContext update];
}

JNIEXPORT void JNICALL Java_OpenGLCanvas_allocOpenGL(JNIEnv *env, jobject canvas)
{
	ContextInfo *ci = getContext(env, canvas);
	
	jboolean result = JNI_FALSE;
    
    // get the AWT
    ci->awt->version = JAWT_VERSION_1_4;
    result = JAWT_GetAWT(env, ci->awt);
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
    }
    assert(result != JNI_FALSE);	
	
    // Get the drawing surface.  This can be safely cached.
    // Anything below the DS (DSI, contexts, etc) 
    // can possibly change/go away and should not be cached.
    ci->ds = ci->awt->GetDrawingSurface(env, canvas);
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
    }
    assert(ci->ds != NULL);
	
	NSLog(@"Alloc Context %d", ci);
}

JNIEXPORT void JNICALL Java_OpenGLCanvas_releaseOpenGL(JNIEnv *env, jobject canvas) 
{
	ContextInfo *ci = getContext(env, canvas);
	NSLog(@"Release Context %d", ci);
	if (ci->openGLContext) {
        if ([ci->openGLContext view] /* == self */) {
            [ci->openGLContext clearDrawable];
        }
        [ci->openGLContext release];
	}
	
    // Free the drawing surface (if not caching it)
    ci->awt->FreeDrawingSurface(ci->ds);
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
    }
	
	freeContext(env, canvas, ci);
}
#endif