Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4502 Serge 1
#include 
2
#include 
3
#include 
4
#include 
5
 
6
#include "render.h"
7
#include 
8
#include 
9
 
4517 Serge 10
void create_mask(struct render *render);
4502 Serge 11
 
12
static int drm_ioctl(int fd, unsigned long request, void *arg)
13
{
14
    ioctl_t  io;
15
 
16
    io.handle   = fd;
17
    io.io_code  = request;
18
    io.input    = arg;
19
    io.inp_size = 64;
20
    io.output   = NULL;
21
    io.out_size = 0;
22
 
23
    return call_service(&io);
24
}
25
 
26
static EGLImageKHR px_create_image(EGLDisplay display, EGLContext context,
27
			 int width, int height, int stride, int name)
28
{
29
	EGLImageKHR image;
30
	EGLint attribs[] = {
31
		EGL_WIDTH, 0,
32
		EGL_HEIGHT, 0,
33
		EGL_DRM_BUFFER_STRIDE_MESA, 0,
34
		EGL_DRM_BUFFER_FORMAT_MESA,
35
		EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
36
		EGL_DRM_BUFFER_USE_MESA,
37
		EGL_DRM_BUFFER_USE_SHARE_MESA |
38
		    EGL_DRM_BUFFER_USE_SCANOUT_MESA,
39
		EGL_NONE
40
	};
41
	attribs[1] = width;
42
	attribs[3] = height;
43
	attribs[5] = stride/4;
44
 
45
    printf("%s w:%d :%d pitch:%d handle %d\n", __FUNCTION__,
46
           width, height, stride, name);
47
 
48
	image = eglCreateImageKHR(display, context, EGL_DRM_BUFFER_MESA,
49
						 (void *) (uintptr_t)name, attribs);
50
 
51
	return image;
52
}
53
 
54
static GLint create_shader(GLenum type, const char *source)
55
{
56
	GLint ok;
57
    GLint shader;
58
 
59
    shader = glCreateShader(type);
60
    if(shader == 0)
61
        goto err;
62
 
63
    glShaderSource(shader, 1, (const GLchar **) &source, NULL);
64
    glCompileShader(shader);
65
    glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
66
	if (!ok) {
67
		GLchar *info;
68
		GLint size;
69
 
70
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
71
		info = malloc(size);
72
 
73
        glGetShaderInfoLog(shader, size, NULL, info);
74
		printf("Failed to compile %s: %s\n",
75
                type == GL_FRAGMENT_SHADER ? "FS" : "VS",info);
76
		printf("Program source:\n%s", source);
77
		printf("GLSL compile failure\n");
78
        free(info);
4768 Serge 79
        glDeleteShader(shader);
4502 Serge 80
        shader = 0;
81
	}
82
err:
83
    return shader;
84
}
85
 
86
 
87
struct render* create_render(EGLDisplay dpy, EGLSurface surface, int dx, int dy)
88
{
89
    const char *vs_src =
90
	    "attribute vec4 v_position;\n"
91
	    "attribute vec4 v_texcoord0;\n"
92
	    "varying vec2 source_texture;\n"
4523 Serge 93
        "void main()\n"
4502 Serge 94
	    "{\n"
95
	    "	gl_Position = v_position;\n"
96
	    "	source_texture = v_texcoord0.xy;\n"
97
	    "}\n";
98
 
99
	const char *fs_src =
100
	    "varying vec2 source_texture;\n"
4523 Serge 101
        "uniform sampler2D sampler_src;\n"
102
        "uniform sampler2D sampler_mask;\n"
4502 Serge 103
	    "void main()\n"
104
	    "{\n"
4525 Serge 105
        "   float ca = texture2D(sampler_mask, source_texture).r;\n"
4523 Serge 106
        "   gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n"
4502 Serge 107
	    "}\n";
4523 Serge 108
 
4502 Serge 109
    EGLint config_attribs[14];
110
    EGLConfig config;
111
    EGLint num_configs;
112
 
113
    EGLContext context;
114
 
115
    struct drm_i915_fb_info fb;
116
    GLint  vs_shader, fs_shader;
117
    GLenum status;
118
    GLint ret;
119
    int fd;
120
    struct render *render;
121
 
122
 
123
    fd = get_service("DISPLAY");
124
 
125
    memset(&fb, 0, sizeof(fb));
126
    ret = drm_ioctl(fd, SRV_FBINFO, &fb);
127
    if( ret != 0 )
128
    {   printf("failed to get framebuffer info\n");
129
        goto err;
130
    };
131
 
132
    render = (struct render*)malloc(sizeof(struct render));
133
    if(render == NULL)
134
        goto err;
135
 
136
    render->fd  = fd;
137
    render->dpy = dpy;
138
    render->dx  = dx;
139
    render->dy  = dy;
140
 
141
    if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width))
142
        goto err1;
143
 
144
    if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height))
145
        goto err1;
146
 
147
    render->scr_width  = fb.width;
148
    render->scr_height = fb.height;
149
 
150
    render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT);
151
    if(render->front == EGL_NO_IMAGE_KHR)
152
        goto err1;
153
 
154
    render->back  = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK);
155
    if( render->back == EGL_NO_IMAGE_KHR)
156
        goto err2;
157
 
158
 
159
    context = eglGetCurrentContext();
160
 
161
    config_attribs[0] = EGL_RED_SIZE;
162
    config_attribs[1] = 1;
163
    config_attribs[2] = EGL_GREEN_SIZE;
164
    config_attribs[3] = 1;
165
    config_attribs[4] = EGL_BLUE_SIZE;
166
    config_attribs[5] = 1;
167
    config_attribs[6] = EGL_DEPTH_SIZE;
168
    config_attribs[7] = 1;
169
 
170
    config_attribs[8] = EGL_SURFACE_TYPE;
171
    config_attribs[9] = EGL_WINDOW_BIT;
172
 
173
    config_attribs[10] = EGL_RENDERABLE_TYPE;
174
    config_attribs[11] = EGL_OPENGL_BIT;
175
    config_attribs[12] = EGL_NONE;
176
 
177
    if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs)
178
    {
179
        printf("failed to choose a config");
180
        goto err3;
181
    }
182
 
183
    render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
184
    if (!context)
185
    {
186
        printf("failed to create context");
187
        goto err3;
188
    };
189
 
190
    if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context))
191
    {
192
        printf("failed to make window current");
193
        goto err4;
194
    };
195
 
196
 
197
    glGenTextures(2, render->tx_buffers);
198
    if(glGetError() != GL_NO_ERROR)
199
       goto err5;
200
 
201
    glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]);
202
    if(glGetError() != GL_NO_ERROR)
203
       goto err6;
204
 
205
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
206
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
207
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front);
208
    if(glGetError() != GL_NO_ERROR)
209
       goto err6;
210
 
211
    glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]);
212
    if(glGetError() != GL_NO_ERROR)
213
       goto err6;
214
 
215
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
216
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
217
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back);
218
    if(glGetError() != GL_NO_ERROR)
219
       goto err6;
220
 
221
    glBindTexture(GL_TEXTURE_2D, 0);
222
 
4525 Serge 223
    render->back_buffer = EGL_DRM_BUFFER_FRONT;
4502 Serge 224
 
225
    render->screen = px_create_image(dpy,context,fb.width,fb.height,
226
                                     fb.pitch,fb.name);
227
    if(render->screen == EGL_NO_IMAGE_KHR)
228
        goto err6;
229
 
230
    glGenTextures(1, &render->tx_screen);
231
    if(glGetError() != GL_NO_ERROR)
232
       goto err6;
233
 
234
    glBindTexture(GL_TEXTURE_2D, render->tx_screen);
235
    if(glGetError() != GL_NO_ERROR)
236
       goto err7;
237
 
238
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
239
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
240
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen);
241
    if(glGetError() != GL_NO_ERROR)
242
       goto err7;
243
 
244
    glBindTexture(GL_TEXTURE_2D, 0);
245
 
4517 Serge 246
    create_mask(render);
247
 
4502 Serge 248
    glGenFramebuffers(1, &render->framebuffer);
249
    if(glGetError() != GL_NO_ERROR)
250
       goto err8;
251
 
252
    glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer);
253
    if(glGetError() != GL_NO_ERROR)
254
       goto err9;
255
 
256
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
257
                           GL_TEXTURE_2D, render->tx_screen,0);
258
 
259
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
260
    if (status != GL_FRAMEBUFFER_COMPLETE)
261
    {
262
        const char *str;
263
        switch (status)
264
        {
265
            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
266
                 str = "incomplete attachment";
267
                 break;
268
            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
269
                str = "incomplete/missing attachment";
270
                break;
271
            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
272
                str = "incomplete draw buffer";
273
                break;
274
            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
275
                str = "incomplete read buffer";
276
                break;
277
            case GL_FRAMEBUFFER_UNSUPPORTED:
278
                str = "unsupported";
279
                break;
280
            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
281
                str = "incomplete multiple";
282
                break;
283
            default:
284
                str = "unknown error";
285
                break;
286
        }
287
        printf("destination is framebuffer incomplete: %s [%#x]\n", str, status);
288
        goto err9;
289
    }
290
 
291
    glViewport(0, 0, render->scr_width, render->scr_height);
292
    glMatrixMode(GL_PROJECTION);
293
	glLoadIdentity();
294
	glMatrixMode(GL_MODELVIEW);
295
	glLoadIdentity();
296
 
297
    render->blit_prog = glCreateProgram();
298
    if(render->blit_prog == 0)
299
        goto err9;
300
 
301
    vs_shader = create_shader(GL_VERTEX_SHADER,vs_src);
302
    if(vs_shader == 0)
303
        goto err10;
304
 
305
    fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src);
306
    if(fs_shader == 0)
307
        goto err11;
308
 
309
    glAttachShader(render->blit_prog, vs_shader);
310
    glAttachShader(render->blit_prog, fs_shader);
311
    glBindAttribLocation(render->blit_prog, 0, "v_position");
312
    glBindAttribLocation(render->blit_prog, 1, "v_texcoord0");
313
 
314
    glLinkProgram(render->blit_prog);
315
    glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret);
316
    if (!ret)
317
    {
318
        GLchar *info;
319
        GLint size;
320
 
321
        glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size);
322
        info = malloc(size);
323
 
324
        glGetProgramInfoLog(render->blit_prog, size, NULL, info);
325
        printf("Failed to link: %s\n", info);
326
        printf("GLSL link failure\n");
327
        free(info);
4768 Serge 328
        goto err12;
4502 Serge 329
    }
330
 
4523 Serge 331
    render->sampler = glGetUniformLocation(render->blit_prog,"sampler_src");
332
    render->sm_mask = glGetUniformLocation(render->blit_prog,"sampler_mask");
4502 Serge 333
 
4517 Serge 334
    glUseProgram(render->blit_prog);
335
    glUniform1i(render->sampler, 0);
4523 Serge 336
    glUniform1i(render->sm_mask, 1);
4517 Serge 337
 
338
    glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices);
339
    glEnableVertexAttribArray(0);
340
 
4523 Serge 341
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->tc_src);
4517 Serge 342
    glEnableVertexAttribArray(1);
343
 
4526 Serge 344
    render->tc_src[0]    = 0.0;
345
    render->tc_src[1]    = 0.0;
346
    render->tc_src[1*2]  = 1.0;
347
    render->tc_src[1*2+1]= 0.0;
348
    render->tc_src[2*2]  = 1.0;
349
    render->tc_src[2*2+1]= 1.0;
350
    render->tc_src[3*2]  = 0.0;
351
    render->tc_src[3*2+1]= 1.0;
352
 
4523 Serge 353
    glEnable(GL_BLEND);
354
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
355
 
356
    glActiveTexture(GL_TEXTURE1);
357
    glBindTexture(GL_TEXTURE_2D, render->tx_mask);
358
    glTexParameteri(GL_TEXTURE_2D,
359
                  GL_TEXTURE_MIN_FILTER,
360
                  GL_NEAREST);
361
    glTexParameteri(GL_TEXTURE_2D,
362
                  GL_TEXTURE_MAG_FILTER,
363
                  GL_NEAREST);
364
 
4502 Serge 365
    eglMakeCurrent(dpy, surface, surface, context);
366
 
367
    return render;
368
 
4768 Serge 369
err12:
370
    glDeleteShader(fs_shader);
4502 Serge 371
err11:
372
    glDeleteShader(vs_shader);
373
err10:
374
    glDeleteProgram(render->blit_prog);
375
err9:
376
    glDeleteFramebuffers(1, &render->framebuffer);
377
err8:
378
    eglDestroyImageKHR(dpy, render->screen);
379
err7:
380
    glDeleteTextures(1, &render->tx_screen);
381
err6:
382
    glDeleteTextures(2, render->tx_buffers);
383
err5:
384
    eglMakeCurrent(dpy, surface, surface, context);
385
err4:
386
    eglDestroyContext(dpy, render->context);
387
err3:
388
    eglDestroyImageKHR(dpy, render->back);
389
err2:
390
    eglDestroyImageKHR(dpy, render->front);
391
err1:
392
    free(render);
393
err:
394
    return NULL;
395
};
396
 
397
 
4517 Serge 398
void create_mask(struct render *render)
399
{
4525 Serge 400
    struct drm_i915_gem_create create;
4768 Serge 401
    struct drm_gem_close close;
4525 Serge 402
    struct drm_gem_flink flink;
403
 
404
    struct drm_i915_gem_mmap mmap_arg;
4517 Serge 405
    EGLint handle, stride;
4523 Serge 406
    int winw, winh, pitch;
4517 Serge 407
    void *data;
4525 Serge 408
    int ret;
409
    GLuint mask_handle, mask_name;
410
    EGLImageKHR mask_image;
4517 Serge 411
 
412
    glGenTextures(1, &render->tx_mask);
413
    if(glGetError() != GL_NO_ERROR)
4525 Serge 414
       return;
4517 Serge 415
 
416
    glBindTexture(GL_TEXTURE_2D, render->tx_mask);
417
    if(glGetError() != GL_NO_ERROR)
4525 Serge 418
       goto err1;
4517 Serge 419
 
4525 Serge 420
    pitch = (render->width+15) & ~15;
4517 Serge 421
 
4525 Serge 422
    create.size = pitch *render->height;
423
    create.handle = 0;
424
    ret = drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
425
    if(ret != 0)
426
        goto err1;
4517 Serge 427
 
4768 Serge 428
    mask_handle = create.handle;
4525 Serge 429
    flink.handle = create.handle;
430
    ret = drm_ioctl(render->fd, DRM_IOCTL_GEM_FLINK, &flink);
431
    if (ret != 0)
432
        goto err2;
4523 Serge 433
 
4525 Serge 434
    mask_name = flink.name;
4523 Serge 435
 
4525 Serge 436
    printf("create mask bo handle %d name %d\n", create.handle, flink.name);
4517 Serge 437
 
4525 Serge 438
    EGLint attribs[] = {
439
        EGL_WIDTH, 0,
440
        EGL_HEIGHT, 0,
441
        EGL_DRM_BUFFER_STRIDE_MESA, 0,
442
        EGL_DRM_BUFFER_FORMAT_MESA,
443
        EGL_DRM_BUFFER_FORMAT_R8_MESA,
444
        EGL_DRM_BUFFER_USE_MESA,
445
        EGL_DRM_BUFFER_USE_SHARE_MESA,
446
        EGL_NONE
447
    };
448
    attribs[1] = pitch;
449
    attribs[3] = render->height;
450
    attribs[5] = pitch;
4517 Serge 451
 
4525 Serge 452
    mask_image = eglCreateImageKHR(render->dpy, render->context, EGL_DRM_BUFFER_MESA,
453
                         (void *) (uintptr_t)mask_name, attribs);
454
    printf("create mask image %p\n", mask_image);
4768 Serge 455
    if(mask_image == NULL)
456
        goto err2
4517 Serge 457
 
4525 Serge 458
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
459
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
4517 Serge 460
 
4525 Serge 461
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mask_image);
462
 
463
    if(glGetError() != GL_NO_ERROR)
4768 Serge 464
       goto err3;
4525 Serge 465
 
4517 Serge 466
    glBindTexture(GL_TEXTURE_2D, 0);
467
 
4525 Serge 468
    mmap_arg.handle = mask_handle;
4517 Serge 469
    mmap_arg.offset = 0;
4525 Serge 470
    mmap_arg.size = pitch * render->height;
471
    if (drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))
4517 Serge 472
    {
473
        printf("%s: failed to mmap image %p handle=%d, %d bytes, into CPU domain\n",
4525 Serge 474
               __FUNCTION__, mask_image, mask_handle, pitch * render->height);
4517 Serge 475
        goto err3;
476
    }
477
 
4525 Serge 478
    render->mask_handle = mask_handle;
479
    render->mask_name   = mask_name;
480
    render->mask_buffer = (void *)(uintptr_t)mmap_arg.addr_ptr;
481
    render->mask_image = mask_image;
4517 Serge 482
 
483
    return;
484
 
485
err3:
4768 Serge 486
    eglDestroyImageKHR(render->dpy, mask_image);
4517 Serge 487
err2:
4768 Serge 488
    close.handle = mask_handle;
489
    (void)drm_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
4517 Serge 490
    glBindTexture(GL_TEXTURE_2D, 0);
491
err1:
492
    glDeleteTextures(1, &render->tx_mask);
493
};