Subversion Repositories Kolibri OS

Rev

Rev 4495 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4464 Serge 1
#include 
2
#include 
3
#include 
4
#include 
5
 
6
#define EGL_EGLEXT_PROTOTYPES
4472 Serge 7
#define GL_GLEXT_PROTOTYPES
8
 
4464 Serge 9
#include "EGL/egl.h"
10
#include "EGL/eglext.h"
11
#include "GL/gl.h"
12
#include "gbm.h"
4472 Serge 13
#include 
4464 Serge 14
#include 
15
#include 
16
 
4498 Serge 17
enum px_buffer
18
{
19
    PX_FRONT = 0,
20
    PX_BACK  = 1
21
};
22
 
23
struct render
24
{
25
    EGLDisplay dpy;
26
    EGLContext context;
27
    GLuint framebuffer;
28
    EGLImageKHR front, back, screen;
29
    GLuint tx_buffers[2];
30
    GLuint tx_screen;
31
    int back_buffer;
32
    GLuint blit_prog;
33
    GLint sampler;
34
    float vertices[8], texcoords[8];
35
};
36
 
37
 
4473 Serge 38
EGLImageKHR px_create_image(EGLDisplay display, EGLContext context,
39
			 int width, int height, int stride, int name);
4485 Serge 40
GLuint create_framebuffer(int width, int height, GLuint *tex);
41
GLint create_shader(GLenum type, const char *source);
4498 Serge 42
struct render* create_render(EGLDisplay dpy, EGLSurface surface);
43
void blit_texture(struct render *render, GLuint tex, int x, int y, int w, int h);
44
void render_swap_buffers(struct render *render, int x, int y, int w, int h);
4472 Serge 45
 
4464 Serge 46
int main()
47
{
48
    struct gbm_device *gbm;
49
    struct gbm_surface  *gs;
4498 Serge 50
    struct render *render;
4464 Serge 51
 
52
    EGLDisplay dpy;
53
    EGLint major, minor;
54
 
55
    EGLContext context;
56
    EGLSurface surface;
4498 Serge 57
 
4464 Serge 58
    EGLConfig config;
59
 
60
    EGLint config_attribs[32];
61
    EGLint num_configs, i;
62
 
63
    int fd;
64
 
65
    fd = get_service("DISPLAY");
66
    gbm = gbm_create_device(fd);
67
    if( gbm == NULL){
68
        printf("failed to initialize GBM device");
69
        return 1;
70
    };
71
 
4472 Serge 72
    init_pixlib(HW_BIT_BLIT);
73
 
4464 Serge 74
    dpy = eglGetDisplay((EGLNativeDisplayType)gbm);
75
 
76
    if (!eglInitialize(dpy, &major, &minor))
77
        printf("failed to initialize EGL display");
78
 
79
    printf("EGL_VERSION = %s\n", eglQueryString(dpy, EGL_VERSION));
80
    printf("EGL_VENDOR = %s\n", eglQueryString(dpy, EGL_VENDOR));
81
    printf("EGL_EXTENSIONS = %s\n", eglQueryString(dpy, EGL_EXTENSIONS));
82
    printf("EGL_CLIENT_APIS = %s\n",eglQueryString(dpy, EGL_CLIENT_APIS));
83
 
84
    i = 0;
85
    config_attribs[i++] = EGL_RED_SIZE;
86
    config_attribs[i++] = 1;
87
    config_attribs[i++] = EGL_GREEN_SIZE;
88
    config_attribs[i++] = 1;
89
    config_attribs[i++] = EGL_BLUE_SIZE;
90
    config_attribs[i++] = 1;
91
    config_attribs[i++] = EGL_DEPTH_SIZE;
92
    config_attribs[i++] = 1;
93
 
94
    config_attribs[i++] = EGL_SURFACE_TYPE;
95
    config_attribs[i++] = EGL_WINDOW_BIT;
96
 
97
    config_attribs[i++] = EGL_RENDERABLE_TYPE;
98
    config_attribs[i++] = EGL_OPENGL_BIT;
99
    config_attribs[i] = EGL_NONE;
100
 
101
    if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs)
102
        printf("failed to choose a config");
103
 
104
    eglBindAPI(EGL_OPENGL_API);
105
    context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
106
    if (!context)
107
        printf("failed to create context");
108
 
4495 Serge 109
    gs = gbm_surface_create(gbm, 400, 300, GBM_BO_FORMAT_ARGB8888, GBM_BO_USE_RENDERING);
4464 Serge 110
 
111
    BeginDraw();
112
    DrawWindow(20, 20, 400+9, 300+24, "gl-render", 0x000000, 0x74);
113
    EndDraw();
114
 
4495 Serge 115
    surface = eglCreateWindowSurface(dpy,config, (EGLNativeWindowType)gs, NULL);
116
    if (surface == EGL_NO_SURFACE)
117
        printf("failed to create surface");
4464 Serge 118
 
4495 Serge 119
    if (!eglMakeCurrent(dpy, surface, surface, context))
4464 Serge 120
        printf("failed to make window current");
121
 
4472 Serge 122
 
4495 Serge 123
 
4485 Serge 124
    glMatrixMode(GL_PROJECTION);
125
	glLoadIdentity();
126
    glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
127
	glMatrixMode(GL_MODELVIEW);
128
	glLoadIdentity();
129
 
130
	glViewport(0, 0, 400, 300);
131
 
132
    glClearColor( 0, 0, 0, 1);
133
 
134
    glClear(GL_COLOR_BUFFER_BIT);
135
 
136
    glBegin(GL_QUADS);
137
    glColor3f(1,0,0);
138
    glVertex3f( 0.9, -0.9, -30.0);
139
    glColor3f(1,1,0);
140
    glVertex3f( 0.9,  0.9, -30.0);
141
 
142
    glColor3f(1,1,1);
143
    glVertex3f( 0.1,  0.9, -30.0);
144
    glColor3f(1,0,1);
145
    glVertex3f( 0.1, -0.9, -30.0);
146
    glEnd();
147
 
148
    glFlush();
149
 
4498 Serge 150
  asm volatile ("int3");
4485 Serge 151
 
4498 Serge 152
    render = create_render(dpy, surface);
153
  	glViewport(0, 0, 1024, 768);
4485 Serge 154
    glMatrixMode(GL_PROJECTION);
155
	glLoadIdentity();
156
	glMatrixMode(GL_MODELVIEW);
157
	glLoadIdentity();
4464 Serge 158
 
4498 Serge 159
    render_swap_buffers(render, 20, 20, 400, 300);
4464 Serge 160
 
161
    glFinish();
162
    eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
4473 Serge 163
//    eglDestroySurface(dpy, surface);
164
  //  gbm_surface_destroy(gs);
4464 Serge 165
    eglDestroyContext(dpy, context);
166
    eglTerminate(dpy);
167
 
168
    while(1)
169
    {
170
        delay(1);
171
    }
4472 Serge 172
 
4464 Serge 173
    return 0;
174
}
4472 Serge 175
 
176
int drmIoctl(int fd, unsigned long request, void *arg)
177
{
178
    ioctl_t  io;
179
 
180
    io.handle   = fd;
181
    io.io_code  = request;
182
    io.input    = arg;
183
    io.inp_size = 64;
184
    io.output   = NULL;
185
    io.out_size = 0;
186
 
187
    return call_service(&io);
188
}
189
 
4473 Serge 190
EGLImageKHR px_create_image(EGLDisplay display, EGLContext context,
191
			 int width, int height, int stride, int name)
4472 Serge 192
{
193
	EGLImageKHR image;
194
	EGLint attribs[] = {
195
		EGL_WIDTH, 0,
196
		EGL_HEIGHT, 0,
197
		EGL_DRM_BUFFER_STRIDE_MESA, 0,
198
		EGL_DRM_BUFFER_FORMAT_MESA,
199
		EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
200
		EGL_DRM_BUFFER_USE_MESA,
201
		EGL_DRM_BUFFER_USE_SHARE_MESA |
202
		    EGL_DRM_BUFFER_USE_SCANOUT_MESA,
203
		EGL_NONE
204
	};
205
	attribs[1] = width;
206
	attribs[3] = height;
4485 Serge 207
	attribs[5] = stride/4;
4473 Serge 208
 
209
    printf("%s w:%d :%d pitch:%d handle %d\n", __FUNCTION__,
210
           width, height, stride, name);
211
 
4472 Serge 212
	image = eglCreateImageKHR(display, context, EGL_DRM_BUFFER_MESA,
213
						 (void *) (uintptr_t)name, attribs);
214
 
215
	return image;
216
}
4485 Serge 217
 
218
GLint create_shader(GLenum type, const char *source)
219
{
220
	GLint ok;
4498 Serge 221
    GLint shader;
4485 Serge 222
 
4498 Serge 223
    shader = glCreateShader(type);
224
    if(shader == 0)
225
        goto err;
226
 
227
    glShaderSource(shader, 1, (const GLchar **) &source, NULL);
228
    glCompileShader(shader);
229
    glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
4485 Serge 230
	if (!ok) {
231
		GLchar *info;
232
		GLint size;
233
 
4498 Serge 234
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
4485 Serge 235
		info = malloc(size);
236
 
4498 Serge 237
        glGetShaderInfoLog(shader, size, NULL, info);
4485 Serge 238
		printf("Failed to compile %s: %s\n",
239
                type == GL_FRAGMENT_SHADER ? "FS" : "VS",info);
240
		printf("Program source:\n%s", source);
241
		printf("GLSL compile failure\n");
4498 Serge 242
        free(info);
243
        glDeleteProgram(shader);
244
        shader = 0;
4485 Serge 245
	}
4498 Serge 246
err:
247
    return shader;
248
}
4485 Serge 249
 
4498 Serge 250
 
251
struct render* create_render(EGLDisplay dpy, EGLSurface surface)
252
{
253
    const char *vs_src =
254
	    "attribute vec4 v_position;\n"
255
	    "attribute vec4 v_texcoord0;\n"
256
	    "varying vec2 source_texture;\n"
257
	    "void main()\n"
258
	    "{\n"
259
	    "	gl_Position = v_position;\n"
260
	    "	source_texture = v_texcoord0.xy;\n"
261
	    "}\n";
262
 
263
	const char *fs_src =
264
//	    "precision mediump float;\n"
265
	    "varying vec2 source_texture;\n"
266
	    "uniform sampler2D sampler;\n"
267
	    "void main()\n"
268
	    "{\n"
269
	    "   vec3 cg = texture2D(sampler, source_texture).rgb;\n"
270
	    "   gl_FragColor = vec4(cg.r,cg.g,cg.b,1.0);\n"
271
	    "}\n";
272
    EGLint config_attribs[14];
273
    EGLConfig config;
274
    EGLint num_configs;
275
 
276
    EGLContext context;
277
 
278
    struct drm_i915_fb_info fb;
279
    GLint  vs_shader, fs_shader;
280
    GLenum status;
281
    GLint ret;
282
    int fd;
283
    struct render *render;
284
 
285
 
286
 
287
    fd = get_service("DISPLAY");
288
 
289
    memset(&fb, 0, sizeof(fb));
290
    ret = drmIoctl(fd, SRV_FBINFO, &fb);
291
    if( ret != 0 )
292
    {   printf("failed to get framebuffer info\n");
293
        goto err;
294
    };
295
 
296
    render = (struct render*)malloc(sizeof(struct render));
297
    if(render == NULL)
298
        goto err;
299
 
300
    render->dpy = dpy;
301
 
302
    render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT);
303
    if(render->front == EGL_NO_IMAGE_KHR)
304
        goto err1;
305
 
306
    render->back  = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK);
307
    if( render->back == EGL_NO_IMAGE_KHR)
308
        goto err2;
309
 
310
    glGenTextures(2, render->tx_buffers);
311
    if(glGetError() != GL_NO_ERROR)
312
       goto err3;
313
 
314
    glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]);
315
    if(glGetError() != GL_NO_ERROR)
316
       goto err4;
317
 
318
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
319
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
320
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front);
321
    if(glGetError() != GL_NO_ERROR)
322
       goto err4;
323
 
324
    glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]);
325
    if(glGetError() != GL_NO_ERROR)
326
       goto err4;
327
 
328
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
329
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
330
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back);
331
    if(glGetError() != GL_NO_ERROR)
332
       goto err4;
333
 
334
    glBindTexture(GL_TEXTURE_2D, 0);
335
 
336
    render->back_buffer = EGL_DRM_BUFFER_BACK;
337
 
338
    context = eglGetCurrentContext();
339
 
340
    config_attribs[0] = EGL_RED_SIZE;
341
    config_attribs[1] = 1;
342
    config_attribs[2] = EGL_GREEN_SIZE;
343
    config_attribs[3] = 1;
344
    config_attribs[4] = EGL_BLUE_SIZE;
345
    config_attribs[5] = 1;
346
    config_attribs[6] = EGL_DEPTH_SIZE;
347
    config_attribs[7] = 1;
348
 
349
    config_attribs[8] = EGL_SURFACE_TYPE;
350
    config_attribs[9] = EGL_WINDOW_BIT;
351
 
352
    config_attribs[10] = EGL_RENDERABLE_TYPE;
353
    config_attribs[11] = EGL_OPENGL_BIT;
354
    config_attribs[12] = EGL_NONE;
355
 
356
    if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs)
357
    {
358
        printf("failed to choose a config");
359
        goto err4;
360
    }
361
 
362
    render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
363
    if (!context)
364
    {
365
        printf("failed to create context");
366
        goto err4;
367
    };
368
 
369
    if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context))
370
    {
371
        printf("failed to make window current");
372
        goto err5;
373
    };
374
 
375
    render->screen = px_create_image(dpy,context,fb.width,fb.height,
376
                                     fb.pitch,fb.name);
377
    if(render->screen == EGL_NO_IMAGE_KHR)
378
        goto err6;
379
 
380
    glGenTextures(1, &render->tx_screen);
381
    if(glGetError() != GL_NO_ERROR)
382
       goto err6;
383
 
384
    glBindTexture(GL_TEXTURE_2D, render->tx_screen);
385
    if(glGetError() != GL_NO_ERROR)
386
       goto err7;
387
 
388
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
389
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
390
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen);
391
    if(glGetError() != GL_NO_ERROR)
392
       goto err7;
393
 
394
    glBindTexture(GL_TEXTURE_2D, 0);
395
 
396
    glGenFramebuffers(1, &render->framebuffer);
397
    if(glGetError() != GL_NO_ERROR)
398
       goto err8;
399
 
400
    glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer);
401
    if(glGetError() != GL_NO_ERROR)
402
       goto err9;
403
 
404
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
405
                           GL_TEXTURE_2D, render->tx_screen,0);
406
 
407
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
408
    if (status != GL_FRAMEBUFFER_COMPLETE)
409
    {
410
        const char *str;
411
        switch (status)
412
        {
413
            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
414
                 str = "incomplete attachment";
415
                 break;
416
            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
417
                str = "incomplete/missing attachment";
418
                break;
419
            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
420
                str = "incomplete draw buffer";
421
                break;
422
            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
423
                str = "incomplete read buffer";
424
                break;
425
            case GL_FRAMEBUFFER_UNSUPPORTED:
426
                str = "unsupported";
427
                break;
428
            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
429
                str = "incomplete multiple";
430
                break;
431
            default:
432
                str = "unknown error";
433
                break;
434
        }
435
        printf("destination is framebuffer incomplete: %s [%#x]\n", str, status);
436
        goto err9;
437
    }
438
 
439
    render->blit_prog = glCreateProgram();
440
    if(render->blit_prog == 0)
441
        goto err9;
442
 
443
    vs_shader = create_shader(GL_VERTEX_SHADER,vs_src);
444
    if(vs_shader == 0)
445
        goto err10;
446
 
447
    fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src);
448
    if(fs_shader == 0)
449
        goto err11;
450
 
451
    glAttachShader(render->blit_prog, vs_shader);
452
    glAttachShader(render->blit_prog, fs_shader);
453
    glBindAttribLocation(render->blit_prog, 0, "v_position");
454
    glBindAttribLocation(render->blit_prog, 1, "v_texcoord0");
455
    glLinkProgram(render->blit_prog);
456
 
457
    glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret);
458
    if (!ret)
459
    {
460
        GLchar *info;
461
        GLint size;
462
 
463
        glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size);
464
        info = malloc(size);
465
 
466
        glGetProgramInfoLog(render->blit_prog, size, NULL, info);
467
        printf("Failed to link: %s\n", info);
468
        printf("GLSL link failure\n");
469
        free(info);
470
    }
471
 
472
    render->sampler = glGetUniformLocation(render->blit_prog,"sampler");
473
 
474
    eglMakeCurrent(dpy, surface, surface, context);
475
 
476
    return render;
477
 
478
err11:
479
    glDeleteShader(vs_shader);
480
err10:
481
    glDeleteProgram(render->blit_prog);
482
err9:
483
    glDeleteFramebuffers(1, &render->framebuffer);
484
err8:
485
    eglDestroyImageKHR(dpy, render->screen);
486
err7:
487
    glDeleteTextures(1, &render->tx_screen);
488
err6:
489
    eglMakeCurrent(dpy, surface, surface, context);
490
err5:
491
    eglDestroyContext(dpy, render->context);
492
err4:
493
    glDeleteTextures(2, render->tx_buffers);
494
err3:
495
    eglDestroyImageKHR(dpy, render->back);
496
err2:
497
    eglDestroyImageKHR(dpy, render->front);
498
err1:
499
    free(render);
500
err:
501
    return NULL;
502
};
503
 
504
void render_swap_buffers(struct render *render, int x, int y, int w, int h)
505
{
506
    EGLContext context;
507
    EGLSurface draw, read;
508
 
509
    float dst_xscale, dst_yscale;
510
    float *vertices  = render->vertices;
511
    float *texcoords = render->texcoords;
512
    int r, b;
513
 
514
    if(render == NULL)
515
        return;
516
 
517
    context = eglGetCurrentContext();
518
    draw = eglGetCurrentSurface(EGL_DRAW);
519
    read = eglGetCurrentSurface(EGL_READ);
520
 
521
    eglSwapBuffers(render->dpy,draw);
522
 
523
    if (!eglMakeCurrent(render->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context))
524
    {
525
        printf("failed to make window current");
526
        goto err1;
527
    };
528
 
529
    glUseProgram(render->blit_prog);
530
    glUniform1i(render->sampler, 0);
531
 
532
    glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices);
533
    glEnableVertexAttribArray(0);
534
 
535
    glActiveTexture(GL_TEXTURE0);
536
    glBindTexture(GL_TEXTURE_2D, render->tx_buffers[render->back_buffer]);
537
    glTexParameteri(GL_TEXTURE_2D,
538
                  GL_TEXTURE_MIN_FILTER,
539
                  GL_NEAREST);
540
    glTexParameteri(GL_TEXTURE_2D,
541
                  GL_TEXTURE_MAG_FILTER,
542
                  GL_NEAREST);
543
 
544
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->texcoords);
545
    glEnableVertexAttribArray(1);
546
 
547
    dst_xscale = 1.0/1024;
548
    dst_yscale = 1.0/768;
549
 
550
    r = x+w-1;
551
    b = y+h-1;
552
 
553
    float t0, t1, t2, t5;
554
 
555
    vertices[0]     = t0 = 2*x*dst_xscale - 1.0;
556
    vertices[1 * 2] = t2 = 2*r*dst_xscale - 1.0;
557
 
558
    vertices[2 * 2] = t2;
559
    vertices[3 * 2] = t0;
560
 
561
    vertices[1]     = t1 = 2*y*dst_yscale - 1.0;
562
    vertices[2*2+1] = t5 = 2*b*dst_yscale - 1.0;
563
    vertices[1*2+1] = t1;
564
    vertices[3*2+1] = t5;
565
 
566
    texcoords[0]    = 0.0;
567
    texcoords[1]    = 0.0;
568
    texcoords[1*2]  = 1.0;
569
    texcoords[1*2+1]= 0.0;
570
    texcoords[2*2]  = 1.0;
571
    texcoords[2*2+1]= 1.0;
572
    texcoords[3*2]  = 0.0;
573
    texcoords[3*2+1]= 1.0;
574
 
575
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
576
 
577
    glDisableVertexAttribArray(0);
578
    glDisableVertexAttribArray(1);
579
    glDisable(GL_TEXTURE_2D);
580
    glUseProgram(0);
581
 
582
    render->back_buffer++;
583
    render->back_buffer&=1;
584
 
585
err1:
586
    eglMakeCurrent(render->dpy, draw, read, context);
4485 Serge 587
}
588
 
4498 Serge 589
#if 0
4485 Serge 590
GLuint create_framebuffer(int width, int height, GLuint *tex)
591
{
592
    GLuint buffer;
593
 
594
    glGenTextures(1, tex);
595
    glBindTexture(GL_TEXTURE_2D, *tex);
596
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
597
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
598
 
599
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
600
			       GL_UNSIGNED_BYTE, NULL);
601
    glBindTexture(GL_TEXTURE_2D, 0);
602
 
603
    glGenFramebuffers(1, &buffer);
604
    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
605
    glFramebufferTexture2D(GL_FRAMEBUFFER,
606
					 GL_COLOR_ATTACHMENT0,
607
					 GL_TEXTURE_2D, *tex,0);
608
   return buffer;
609
}
4498 Serge 610
#endif