Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright 2009, VMware, Inc. |
||
5 | * All Rights Reserved. |
||
6 | * Copyright (C) 2010 LunarG Inc. |
||
7 | * |
||
8 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
9 | * copy of this software and associated documentation files (the "Software"), |
||
10 | * to deal in the Software without restriction, including without limitation |
||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
12 | * and/or sell copies of the Software, and to permit persons to whom the |
||
13 | * Software is furnished to do so, subject to the following conditions: |
||
14 | * |
||
15 | * The above copyright notice and this permission notice shall be included |
||
16 | * in all copies or substantial portions of the Software. |
||
17 | * |
||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
22 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
23 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
24 | * OTHER DEALINGS IN THE SOFTWARE. |
||
25 | * |
||
26 | * Authors: |
||
27 | * Keith Whitwell |
||
28 | * |
||
29 | */ |
||
30 | |||
31 | #include "util/u_memory.h" |
||
32 | #include "util/u_inlines.h" |
||
33 | #include "util/u_format.h" |
||
34 | #include "util/u_debug.h" |
||
35 | #include "state_tracker/drm_driver.h" |
||
36 | |||
37 | #include "dri_screen.h" |
||
38 | #include "dri_context.h" |
||
39 | #include "dri_drawable.h" |
||
40 | #include "dri2_buffer.h" |
||
41 | |||
42 | /** |
||
43 | * DRI2 flush extension. |
||
44 | */ |
||
45 | static void |
||
46 | dri2_flush_drawable(__DRIdrawable *dPriv) |
||
47 | { |
||
48 | dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); |
||
49 | } |
||
50 | |||
51 | static void |
||
52 | dri2_invalidate_drawable(__DRIdrawable *dPriv) |
||
53 | { |
||
54 | struct dri_drawable *drawable = dri_drawable(dPriv); |
||
55 | |||
56 | dri2InvalidateDrawable(dPriv); |
||
57 | drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; |
||
58 | |||
59 | p_atomic_inc(&drawable->base.stamp); |
||
60 | } |
||
61 | |||
62 | static const __DRI2flushExtension dri2FlushExtension = { |
||
63 | { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, |
||
64 | dri2_flush_drawable, |
||
65 | dri2_invalidate_drawable, |
||
66 | dri_flush, |
||
67 | }; |
||
68 | |||
69 | /** |
||
70 | * Retrieve __DRIbuffer from the DRI loader. |
||
71 | */ |
||
72 | static __DRIbuffer * |
||
73 | dri2_drawable_get_buffers(struct dri_drawable *drawable, |
||
74 | const enum st_attachment_type *atts, |
||
75 | unsigned *count) |
||
76 | { |
||
77 | __DRIdrawable *dri_drawable = drawable->dPriv; |
||
78 | struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; |
||
79 | boolean with_format; |
||
80 | __DRIbuffer *buffers; |
||
81 | int num_buffers; |
||
82 | unsigned attachments[10]; |
||
83 | unsigned num_attachments, i; |
||
84 | |||
85 | assert(loader); |
||
86 | with_format = dri_with_format(drawable->sPriv); |
||
87 | |||
88 | num_attachments = 0; |
||
89 | |||
90 | /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ |
||
91 | if (!with_format) |
||
92 | attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; |
||
93 | |||
94 | for (i = 0; i < *count; i++) { |
||
95 | enum pipe_format format; |
||
96 | unsigned bind; |
||
97 | int att, depth; |
||
98 | |||
99 | dri_drawable_get_format(drawable, atts[i], &format, &bind); |
||
100 | if (format == PIPE_FORMAT_NONE) |
||
101 | continue; |
||
102 | |||
103 | switch (atts[i]) { |
||
104 | case ST_ATTACHMENT_FRONT_LEFT: |
||
105 | /* already added */ |
||
106 | if (!with_format) |
||
107 | continue; |
||
108 | att = __DRI_BUFFER_FRONT_LEFT; |
||
109 | break; |
||
110 | case ST_ATTACHMENT_BACK_LEFT: |
||
111 | att = __DRI_BUFFER_BACK_LEFT; |
||
112 | break; |
||
113 | case ST_ATTACHMENT_FRONT_RIGHT: |
||
114 | att = __DRI_BUFFER_FRONT_RIGHT; |
||
115 | break; |
||
116 | case ST_ATTACHMENT_BACK_RIGHT: |
||
117 | att = __DRI_BUFFER_BACK_RIGHT; |
||
118 | break; |
||
119 | default: |
||
120 | continue; |
||
121 | } |
||
122 | |||
123 | /* |
||
124 | * In this switch statement we must support all formats that |
||
125 | * may occur as the stvis->color_format. |
||
126 | */ |
||
127 | switch(format) { |
||
128 | case PIPE_FORMAT_B8G8R8A8_UNORM: |
||
129 | depth = 32; |
||
130 | break; |
||
131 | case PIPE_FORMAT_B8G8R8X8_UNORM: |
||
132 | depth = 24; |
||
133 | break; |
||
134 | case PIPE_FORMAT_B5G6R5_UNORM: |
||
135 | depth = 16; |
||
136 | break; |
||
137 | default: |
||
138 | depth = util_format_get_blocksizebits(format); |
||
139 | assert(!"Unexpected format in dri2_drawable_get_buffers()"); |
||
140 | } |
||
141 | |||
142 | attachments[num_attachments++] = att; |
||
143 | if (with_format) { |
||
144 | attachments[num_attachments++] = depth; |
||
145 | } |
||
146 | } |
||
147 | |||
148 | if (with_format) { |
||
149 | num_attachments /= 2; |
||
150 | buffers = loader->getBuffersWithFormat(dri_drawable, |
||
151 | &dri_drawable->w, &dri_drawable->h, |
||
152 | attachments, num_attachments, |
||
153 | &num_buffers, dri_drawable->loaderPrivate); |
||
154 | } |
||
155 | else { |
||
156 | buffers = loader->getBuffers(dri_drawable, |
||
157 | &dri_drawable->w, &dri_drawable->h, |
||
158 | attachments, num_attachments, |
||
159 | &num_buffers, dri_drawable->loaderPrivate); |
||
160 | } |
||
161 | |||
162 | if (buffers) |
||
163 | *count = num_buffers; |
||
164 | |||
165 | return buffers; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Process __DRIbuffer and convert them into pipe_resources. |
||
170 | */ |
||
171 | static void |
||
172 | dri2_drawable_process_buffers(struct dri_context *ctx, |
||
173 | struct dri_drawable *drawable, |
||
174 | __DRIbuffer *buffers, unsigned buffer_count, |
||
175 | const enum st_attachment_type *atts, |
||
176 | unsigned att_count) |
||
177 | { |
||
178 | struct dri_screen *screen = dri_screen(drawable->sPriv); |
||
179 | __DRIdrawable *dri_drawable = drawable->dPriv; |
||
180 | struct pipe_resource templ; |
||
181 | struct winsys_handle whandle; |
||
182 | boolean alloc_depthstencil = FALSE; |
||
183 | unsigned i, j, bind; |
||
184 | |||
185 | if (drawable->old_num == buffer_count && |
||
186 | drawable->old_w == dri_drawable->w && |
||
187 | drawable->old_h == dri_drawable->h && |
||
188 | memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count) == 0) |
||
189 | return; |
||
190 | |||
191 | /* See if we need a depth-stencil buffer. */ |
||
192 | for (i = 0; i < att_count; i++) { |
||
193 | if (atts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { |
||
194 | alloc_depthstencil = TRUE; |
||
195 | break; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | /* Delete the resources we won't need. */ |
||
200 | for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { |
||
201 | /* Don't delete the depth-stencil buffer, we can reuse it. */ |
||
202 | if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) |
||
203 | continue; |
||
204 | |||
205 | pipe_resource_reference(&drawable->textures[i], NULL); |
||
206 | } |
||
207 | |||
208 | if (drawable->stvis.samples > 1) { |
||
209 | for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { |
||
210 | boolean del = TRUE; |
||
211 | |||
212 | /* Don't delete MSAA resources for the attachments which are enabled, |
||
213 | * we can reuse them. */ |
||
214 | for (j = 0; j < att_count; j++) { |
||
215 | if (i == atts[j]) { |
||
216 | del = FALSE; |
||
217 | break; |
||
218 | } |
||
219 | } |
||
220 | |||
221 | if (del) { |
||
222 | pipe_resource_reference(&drawable->msaa_textures[i], NULL); |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | |||
227 | memset(&templ, 0, sizeof(templ)); |
||
228 | templ.target = screen->target; |
||
229 | templ.last_level = 0; |
||
230 | templ.width0 = dri_drawable->w; |
||
231 | templ.height0 = dri_drawable->h; |
||
232 | templ.depth0 = 1; |
||
233 | templ.array_size = 1; |
||
234 | |||
235 | memset(&whandle, 0, sizeof(whandle)); |
||
236 | |||
237 | /* Process DRI-provided buffers and get pipe_resources. */ |
||
238 | for (i = 0; i < buffer_count; i++) { |
||
239 | __DRIbuffer *buf = &buffers[i]; |
||
240 | enum st_attachment_type statt; |
||
241 | enum pipe_format format; |
||
242 | |||
243 | switch (buf->attachment) { |
||
244 | case __DRI_BUFFER_FRONT_LEFT: |
||
245 | if (!screen->auto_fake_front) { |
||
246 | continue; /* invalid attachment */ |
||
247 | } |
||
248 | /* fallthrough */ |
||
249 | case __DRI_BUFFER_FAKE_FRONT_LEFT: |
||
250 | statt = ST_ATTACHMENT_FRONT_LEFT; |
||
251 | break; |
||
252 | case __DRI_BUFFER_BACK_LEFT: |
||
253 | statt = ST_ATTACHMENT_BACK_LEFT; |
||
254 | break; |
||
255 | default: |
||
256 | continue; /* invalid attachment */ |
||
257 | } |
||
258 | |||
259 | dri_drawable_get_format(drawable, statt, &format, &bind); |
||
260 | if (format == PIPE_FORMAT_NONE) |
||
261 | continue; |
||
262 | |||
263 | templ.format = format; |
||
264 | templ.bind = bind; |
||
265 | whandle.handle = buf->name; |
||
266 | whandle.stride = buf->pitch; |
||
267 | |||
268 | drawable->textures[statt] = |
||
269 | screen->base.screen->resource_from_handle(screen->base.screen, |
||
270 | &templ, &whandle); |
||
271 | assert(drawable->textures[statt]); |
||
272 | } |
||
273 | |||
274 | /* Allocate private MSAA colorbuffers. */ |
||
275 | if (drawable->stvis.samples > 1) { |
||
276 | for (i = 0; i < att_count; i++) { |
||
277 | enum st_attachment_type att = atts[i]; |
||
278 | |||
279 | if (att == ST_ATTACHMENT_DEPTH_STENCIL) |
||
280 | continue; |
||
281 | |||
282 | if (drawable->textures[att]) { |
||
283 | templ.format = drawable->textures[att]->format; |
||
284 | templ.bind = drawable->textures[att]->bind; |
||
285 | templ.nr_samples = drawable->stvis.samples; |
||
286 | |||
287 | /* Try to reuse the resource. |
||
288 | * (the other resource parameters should be constant) |
||
289 | */ |
||
290 | if (!drawable->msaa_textures[att] || |
||
291 | drawable->msaa_textures[att]->width0 != templ.width0 || |
||
292 | drawable->msaa_textures[att]->height0 != templ.height0) { |
||
293 | /* Allocate a new one. */ |
||
294 | pipe_resource_reference(&drawable->msaa_textures[att], NULL); |
||
295 | |||
296 | drawable->msaa_textures[att] = |
||
297 | screen->base.screen->resource_create(screen->base.screen, |
||
298 | &templ); |
||
299 | assert(drawable->msaa_textures[att]); |
||
300 | |||
301 | /* If there are any MSAA resources, we should initialize them |
||
302 | * such that they contain the same data as the single-sample |
||
303 | * resources we just got from the X server. |
||
304 | * |
||
305 | * The reason for this is that the state tracker (and |
||
306 | * therefore the app) can access the MSAA resources only. |
||
307 | * The single-sample resources are not exposed |
||
308 | * to the state tracker. |
||
309 | * |
||
310 | */ |
||
311 | dri_pipe_blit(ctx->st->pipe, |
||
312 | drawable->msaa_textures[att], |
||
313 | drawable->textures[att]); |
||
314 | } |
||
315 | } |
||
316 | else { |
||
317 | pipe_resource_reference(&drawable->msaa_textures[att], NULL); |
||
318 | } |
||
319 | } |
||
320 | } |
||
321 | |||
322 | /* Allocate a private depth-stencil buffer. */ |
||
323 | if (alloc_depthstencil) { |
||
324 | enum st_attachment_type att = ST_ATTACHMENT_DEPTH_STENCIL; |
||
325 | struct pipe_resource **zsbuf; |
||
326 | enum pipe_format format; |
||
327 | unsigned bind; |
||
328 | |||
329 | dri_drawable_get_format(drawable, att, &format, &bind); |
||
330 | |||
331 | if (format) { |
||
332 | templ.format = format; |
||
333 | templ.bind = bind; |
||
334 | |||
335 | if (drawable->stvis.samples > 1) { |
||
336 | templ.nr_samples = drawable->stvis.samples; |
||
337 | zsbuf = &drawable->msaa_textures[att]; |
||
338 | } |
||
339 | else { |
||
340 | templ.nr_samples = 0; |
||
341 | zsbuf = &drawable->textures[att]; |
||
342 | } |
||
343 | |||
344 | /* Try to reuse the resource. |
||
345 | * (the other resource parameters should be constant) |
||
346 | */ |
||
347 | if (!*zsbuf || |
||
348 | (*zsbuf)->width0 != templ.width0 || |
||
349 | (*zsbuf)->height0 != templ.height0) { |
||
350 | /* Allocate a new one. */ |
||
351 | pipe_resource_reference(zsbuf, NULL); |
||
352 | *zsbuf = screen->base.screen->resource_create(screen->base.screen, |
||
353 | &templ); |
||
354 | assert(*zsbuf); |
||
355 | } |
||
356 | } |
||
357 | else { |
||
358 | pipe_resource_reference(&drawable->msaa_textures[att], NULL); |
||
359 | pipe_resource_reference(&drawable->textures[att], NULL); |
||
360 | } |
||
361 | } |
||
362 | |||
363 | drawable->old_num = buffer_count; |
||
364 | drawable->old_w = dri_drawable->w; |
||
365 | drawable->old_h = dri_drawable->h; |
||
366 | memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count); |
||
367 | } |
||
368 | |||
369 | static __DRIbuffer * |
||
370 | dri2_allocate_buffer(__DRIscreen *sPriv, |
||
371 | unsigned attachment, unsigned format, |
||
372 | int width, int height) |
||
373 | { |
||
374 | struct dri_screen *screen = dri_screen(sPriv); |
||
375 | struct dri2_buffer *buffer; |
||
376 | struct pipe_resource templ; |
||
377 | enum pipe_format pf; |
||
378 | unsigned bind = 0; |
||
379 | struct winsys_handle whandle; |
||
380 | |||
381 | switch (attachment) { |
||
382 | case __DRI_BUFFER_FRONT_LEFT: |
||
383 | case __DRI_BUFFER_FAKE_FRONT_LEFT: |
||
384 | bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; |
||
385 | break; |
||
386 | case __DRI_BUFFER_BACK_LEFT: |
||
387 | bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; |
||
388 | break; |
||
389 | case __DRI_BUFFER_DEPTH: |
||
390 | case __DRI_BUFFER_DEPTH_STENCIL: |
||
391 | case __DRI_BUFFER_STENCIL: |
||
392 | bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ |
||
393 | break; |
||
394 | } |
||
395 | |||
396 | /* because we get the handle and stride */ |
||
397 | bind |= PIPE_BIND_SHARED; |
||
398 | |||
399 | switch (format) { |
||
400 | case 32: |
||
401 | pf = PIPE_FORMAT_B8G8R8A8_UNORM; |
||
402 | break; |
||
403 | case 24: |
||
404 | pf = PIPE_FORMAT_B8G8R8X8_UNORM; |
||
405 | break; |
||
406 | case 16: |
||
407 | pf = PIPE_FORMAT_Z16_UNORM; |
||
408 | break; |
||
409 | default: |
||
410 | return NULL; |
||
411 | } |
||
412 | |||
413 | buffer = CALLOC_STRUCT(dri2_buffer); |
||
414 | if (!buffer) |
||
415 | return NULL; |
||
416 | |||
417 | memset(&templ, 0, sizeof(templ)); |
||
418 | templ.bind = bind; |
||
419 | templ.format = pf; |
||
420 | templ.target = PIPE_TEXTURE_2D; |
||
421 | templ.last_level = 0; |
||
422 | templ.width0 = width; |
||
423 | templ.height0 = height; |
||
424 | templ.depth0 = 1; |
||
425 | templ.array_size = 1; |
||
426 | |||
427 | buffer->resource = |
||
428 | screen->base.screen->resource_create(screen->base.screen, &templ); |
||
429 | if (!buffer->resource) { |
||
430 | FREE(buffer); |
||
431 | return NULL; |
||
432 | } |
||
433 | |||
434 | memset(&whandle, 0, sizeof(whandle)); |
||
435 | whandle.type = DRM_API_HANDLE_TYPE_SHARED; |
||
436 | screen->base.screen->resource_get_handle(screen->base.screen, |
||
437 | buffer->resource, &whandle); |
||
438 | |||
439 | buffer->base.attachment = attachment; |
||
440 | buffer->base.name = whandle.handle; |
||
441 | buffer->base.cpp = util_format_get_blocksize(pf); |
||
442 | buffer->base.pitch = whandle.stride; |
||
443 | |||
444 | return &buffer->base; |
||
445 | } |
||
446 | |||
447 | static void |
||
448 | dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) |
||
449 | { |
||
450 | struct dri2_buffer *buffer = dri2_buffer(bPriv); |
||
451 | |||
452 | pipe_resource_reference(&buffer->resource, NULL); |
||
453 | FREE(buffer); |
||
454 | } |
||
455 | |||
456 | /* |
||
457 | * Backend functions for st_framebuffer interface. |
||
458 | */ |
||
459 | |||
460 | static void |
||
461 | dri2_allocate_textures(struct dri_context *ctx, |
||
462 | struct dri_drawable *drawable, |
||
463 | const enum st_attachment_type *statts, |
||
464 | unsigned statts_count) |
||
465 | { |
||
466 | __DRIbuffer *buffers; |
||
467 | unsigned num_buffers = statts_count; |
||
468 | |||
469 | buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); |
||
470 | if (buffers) |
||
471 | dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers, |
||
472 | statts, statts_count); |
||
473 | } |
||
474 | |||
475 | static void |
||
476 | dri2_flush_frontbuffer(struct dri_context *ctx, |
||
477 | struct dri_drawable *drawable, |
||
478 | enum st_attachment_type statt) |
||
479 | { |
||
480 | __DRIdrawable *dri_drawable = drawable->dPriv; |
||
481 | struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; |
||
482 | |||
483 | if (statt != ST_ATTACHMENT_FRONT_LEFT) |
||
484 | return; |
||
485 | |||
486 | if (drawable->stvis.samples > 1) { |
||
487 | struct pipe_context *pipe = ctx->st->pipe; |
||
488 | |||
489 | /* Resolve the front buffer. */ |
||
490 | dri_pipe_blit(ctx->st->pipe, |
||
491 | drawable->textures[ST_ATTACHMENT_FRONT_LEFT], |
||
492 | drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); |
||
493 | pipe->flush(pipe, NULL, 0); |
||
494 | } |
||
495 | |||
496 | if (loader->flushFrontBuffer) { |
||
497 | loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); |
||
498 | } |
||
499 | } |
||
500 | |||
501 | static void |
||
502 | dri2_update_tex_buffer(struct dri_drawable *drawable, |
||
503 | struct dri_context *ctx, |
||
504 | struct pipe_resource *res) |
||
505 | { |
||
506 | /* no-op */ |
||
507 | } |
||
508 | |||
509 | static __DRIimage * |
||
510 | dri2_lookup_egl_image(struct dri_screen *screen, void *handle) |
||
511 | { |
||
512 | __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; |
||
513 | __DRIimage *img; |
||
514 | |||
515 | if (!loader->lookupEGLImage) |
||
516 | return NULL; |
||
517 | |||
518 | img = loader->lookupEGLImage(screen->sPriv, |
||
519 | handle, screen->sPriv->loaderPrivate); |
||
520 | |||
521 | return img; |
||
522 | } |
||
523 | |||
524 | static __DRIimage * |
||
525 | dri2_create_image_from_name(__DRIscreen *_screen, |
||
526 | int width, int height, int format, |
||
527 | int name, int pitch, void *loaderPrivate) |
||
528 | { |
||
529 | struct dri_screen *screen = dri_screen(_screen); |
||
530 | __DRIimage *img; |
||
531 | struct pipe_resource templ; |
||
532 | struct winsys_handle whandle; |
||
533 | unsigned tex_usage; |
||
534 | enum pipe_format pf; |
||
535 | |||
536 | tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; |
||
537 | |||
538 | switch (format) { |
||
539 | case __DRI_IMAGE_FORMAT_RGB565: |
||
540 | pf = PIPE_FORMAT_B5G6R5_UNORM; |
||
541 | break; |
||
542 | case __DRI_IMAGE_FORMAT_XRGB8888: |
||
543 | pf = PIPE_FORMAT_B8G8R8X8_UNORM; |
||
544 | break; |
||
545 | case __DRI_IMAGE_FORMAT_ARGB8888: |
||
546 | pf = PIPE_FORMAT_B8G8R8A8_UNORM; |
||
547 | break; |
||
548 | case __DRI_IMAGE_FORMAT_ABGR8888: |
||
549 | pf = PIPE_FORMAT_R8G8B8A8_UNORM; |
||
550 | break; |
||
551 | default: |
||
552 | pf = PIPE_FORMAT_NONE; |
||
553 | break; |
||
554 | } |
||
555 | if (pf == PIPE_FORMAT_NONE) |
||
556 | return NULL; |
||
557 | |||
558 | img = CALLOC_STRUCT(__DRIimageRec); |
||
559 | if (!img) |
||
560 | return NULL; |
||
561 | |||
562 | memset(&templ, 0, sizeof(templ)); |
||
563 | templ.bind = tex_usage; |
||
564 | templ.format = pf; |
||
565 | templ.target = screen->target; |
||
566 | templ.last_level = 0; |
||
567 | templ.width0 = width; |
||
568 | templ.height0 = height; |
||
569 | templ.depth0 = 1; |
||
570 | templ.array_size = 1; |
||
571 | |||
572 | memset(&whandle, 0, sizeof(whandle)); |
||
573 | whandle.handle = name; |
||
574 | whandle.stride = pitch * util_format_get_blocksize(pf); |
||
575 | |||
576 | img->texture = screen->base.screen->resource_from_handle(screen->base.screen, |
||
577 | &templ, &whandle); |
||
578 | if (!img->texture) { |
||
579 | FREE(img); |
||
580 | return NULL; |
||
581 | } |
||
582 | |||
583 | img->level = 0; |
||
584 | img->layer = 0; |
||
585 | img->dri_format = format; |
||
586 | img->loader_private = loaderPrivate; |
||
587 | |||
588 | return img; |
||
589 | } |
||
590 | |||
591 | static __DRIimage * |
||
592 | dri2_create_image_from_renderbuffer(__DRIcontext *context, |
||
593 | int renderbuffer, void *loaderPrivate) |
||
594 | { |
||
595 | struct dri_context *ctx = dri_context(context); |
||
596 | |||
597 | if (!ctx->st->get_resource_for_egl_image) |
||
598 | return NULL; |
||
599 | |||
600 | /* TODO */ |
||
601 | return NULL; |
||
602 | } |
||
603 | |||
604 | static __DRIimage * |
||
605 | dri2_create_image(__DRIscreen *_screen, |
||
606 | int width, int height, int format, |
||
607 | unsigned int use, void *loaderPrivate) |
||
608 | { |
||
609 | struct dri_screen *screen = dri_screen(_screen); |
||
610 | __DRIimage *img; |
||
611 | struct pipe_resource templ; |
||
612 | unsigned tex_usage; |
||
613 | enum pipe_format pf; |
||
614 | |||
615 | tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; |
||
616 | if (use & __DRI_IMAGE_USE_SCANOUT) |
||
617 | tex_usage |= PIPE_BIND_SCANOUT; |
||
618 | if (use & __DRI_IMAGE_USE_SHARE) |
||
619 | tex_usage |= PIPE_BIND_SHARED; |
||
620 | if (use & __DRI_IMAGE_USE_CURSOR) { |
||
621 | if (width != 64 || height != 64) |
||
622 | return NULL; |
||
623 | tex_usage |= PIPE_BIND_CURSOR; |
||
624 | } |
||
625 | |||
626 | switch (format) { |
||
627 | case __DRI_IMAGE_FORMAT_RGB565: |
||
628 | pf = PIPE_FORMAT_B5G6R5_UNORM; |
||
629 | break; |
||
630 | case __DRI_IMAGE_FORMAT_XRGB8888: |
||
631 | pf = PIPE_FORMAT_B8G8R8X8_UNORM; |
||
632 | break; |
||
633 | case __DRI_IMAGE_FORMAT_ARGB8888: |
||
634 | pf = PIPE_FORMAT_B8G8R8A8_UNORM; |
||
635 | break; |
||
636 | case __DRI_IMAGE_FORMAT_ABGR8888: |
||
637 | pf = PIPE_FORMAT_R8G8B8A8_UNORM; |
||
638 | break; |
||
639 | default: |
||
640 | pf = PIPE_FORMAT_NONE; |
||
641 | break; |
||
642 | } |
||
643 | if (pf == PIPE_FORMAT_NONE) |
||
644 | return NULL; |
||
645 | |||
646 | img = CALLOC_STRUCT(__DRIimageRec); |
||
647 | if (!img) |
||
648 | return NULL; |
||
649 | |||
650 | memset(&templ, 0, sizeof(templ)); |
||
651 | templ.bind = tex_usage; |
||
652 | templ.format = pf; |
||
653 | templ.target = PIPE_TEXTURE_2D; |
||
654 | templ.last_level = 0; |
||
655 | templ.width0 = width; |
||
656 | templ.height0 = height; |
||
657 | templ.depth0 = 1; |
||
658 | templ.array_size = 1; |
||
659 | |||
660 | img->texture = screen->base.screen->resource_create(screen->base.screen, &templ); |
||
661 | if (!img->texture) { |
||
662 | FREE(img); |
||
663 | return NULL; |
||
664 | } |
||
665 | |||
666 | img->level = 0; |
||
667 | img->layer = 0; |
||
668 | img->dri_format = format; |
||
669 | img->dri_components = 0; |
||
670 | |||
671 | img->loader_private = loaderPrivate; |
||
672 | return img; |
||
673 | } |
||
674 | |||
675 | static GLboolean |
||
676 | dri2_query_image(__DRIimage *image, int attrib, int *value) |
||
677 | { |
||
678 | struct winsys_handle whandle; |
||
679 | memset(&whandle, 0, sizeof(whandle)); |
||
680 | |||
681 | switch (attrib) { |
||
682 | case __DRI_IMAGE_ATTRIB_STRIDE: |
||
683 | image->texture->screen->resource_get_handle(image->texture->screen, |
||
684 | image->texture, &whandle); |
||
685 | *value = whandle.stride; |
||
686 | return GL_TRUE; |
||
687 | case __DRI_IMAGE_ATTRIB_HANDLE: |
||
688 | whandle.type = DRM_API_HANDLE_TYPE_KMS; |
||
689 | image->texture->screen->resource_get_handle(image->texture->screen, |
||
690 | image->texture, &whandle); |
||
691 | *value = whandle.handle; |
||
692 | return GL_TRUE; |
||
693 | case __DRI_IMAGE_ATTRIB_NAME: |
||
694 | whandle.type = DRM_API_HANDLE_TYPE_SHARED; |
||
695 | image->texture->screen->resource_get_handle(image->texture->screen, |
||
696 | image->texture, &whandle); |
||
697 | *value = whandle.handle; |
||
698 | return GL_TRUE; |
||
699 | case __DRI_IMAGE_ATTRIB_FORMAT: |
||
700 | *value = image->dri_format; |
||
701 | return GL_TRUE; |
||
702 | case __DRI_IMAGE_ATTRIB_WIDTH: |
||
703 | *value = image->texture->width0; |
||
704 | return GL_TRUE; |
||
705 | case __DRI_IMAGE_ATTRIB_HEIGHT: |
||
706 | *value = image->texture->height0; |
||
707 | return GL_TRUE; |
||
708 | case __DRI_IMAGE_ATTRIB_COMPONENTS: |
||
709 | if (image->dri_components == 0) |
||
710 | return GL_FALSE; |
||
711 | *value = image->dri_components; |
||
712 | return GL_TRUE; |
||
713 | default: |
||
714 | return GL_FALSE; |
||
715 | } |
||
716 | } |
||
717 | |||
718 | static __DRIimage * |
||
719 | dri2_dup_image(__DRIimage *image, void *loaderPrivate) |
||
720 | { |
||
721 | __DRIimage *img; |
||
722 | |||
723 | img = CALLOC_STRUCT(__DRIimageRec); |
||
724 | if (!img) |
||
725 | return NULL; |
||
726 | |||
727 | img->texture = NULL; |
||
728 | pipe_resource_reference(&img->texture, image->texture); |
||
729 | img->level = image->level; |
||
730 | img->layer = image->layer; |
||
731 | /* This should be 0 for sub images, but dup is also used for base images. */ |
||
732 | img->dri_components = image->dri_components; |
||
733 | img->loader_private = loaderPrivate; |
||
734 | |||
735 | return img; |
||
736 | } |
||
737 | |||
738 | static GLboolean |
||
739 | dri2_validate_usage(__DRIimage *image, unsigned int use) |
||
740 | { |
||
741 | /* |
||
742 | * Gallium drivers are bad at adding usages to the resources |
||
743 | * once opened again in another process, which is the main use |
||
744 | * case for this, so we have to lie. |
||
745 | */ |
||
746 | if (image != NULL) |
||
747 | return GL_TRUE; |
||
748 | else |
||
749 | return GL_FALSE; |
||
750 | } |
||
751 | |||
752 | static __DRIimage * |
||
753 | dri2_from_names(__DRIscreen *screen, int width, int height, int format, |
||
754 | int *names, int num_names, int *strides, int *offsets, |
||
755 | void *loaderPrivate) |
||
756 | { |
||
757 | __DRIimage *img; |
||
758 | int stride, dri_components; |
||
759 | |||
760 | if (num_names != 1) |
||
761 | return NULL; |
||
762 | if (offsets[0] != 0) |
||
763 | return NULL; |
||
764 | |||
765 | switch(format) { |
||
766 | case __DRI_IMAGE_FOURCC_RGB565: |
||
767 | format = __DRI_IMAGE_FORMAT_RGB565; |
||
768 | dri_components = __DRI_IMAGE_COMPONENTS_RGB; |
||
769 | break; |
||
770 | case __DRI_IMAGE_FOURCC_ARGB8888: |
||
771 | format = __DRI_IMAGE_FORMAT_ARGB8888; |
||
772 | dri_components = __DRI_IMAGE_COMPONENTS_RGBA; |
||
773 | break; |
||
774 | case __DRI_IMAGE_FOURCC_XRGB8888: |
||
775 | format = __DRI_IMAGE_FORMAT_XRGB8888; |
||
776 | dri_components = __DRI_IMAGE_COMPONENTS_RGB; |
||
777 | break; |
||
778 | case __DRI_IMAGE_FOURCC_ABGR8888: |
||
779 | format = __DRI_IMAGE_FORMAT_ABGR8888; |
||
780 | dri_components = __DRI_IMAGE_COMPONENTS_RGBA; |
||
781 | break; |
||
782 | case __DRI_IMAGE_FOURCC_XBGR8888: |
||
783 | format = __DRI_IMAGE_FORMAT_XBGR8888; |
||
784 | dri_components = __DRI_IMAGE_COMPONENTS_RGB; |
||
785 | break; |
||
786 | default: |
||
787 | return NULL; |
||
788 | } |
||
789 | |||
790 | /* Strides are in bytes not pixels. */ |
||
791 | stride = strides[0] /4; |
||
792 | |||
793 | img = dri2_create_image_from_name(screen, width, height, format, |
||
794 | names[0], stride, loaderPrivate); |
||
795 | if (img == NULL) |
||
796 | return NULL; |
||
797 | |||
798 | img->dri_components = dri_components; |
||
799 | return img; |
||
800 | } |
||
801 | |||
802 | static __DRIimage * |
||
803 | dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) |
||
804 | { |
||
805 | __DRIimage *img; |
||
806 | |||
807 | if (plane != 0) |
||
808 | return NULL; |
||
809 | |||
810 | if (image->dri_components == 0) |
||
811 | return NULL; |
||
812 | |||
813 | img = dri2_dup_image(image, loaderPrivate); |
||
814 | if (img == NULL) |
||
815 | return NULL; |
||
816 | |||
817 | /* set this to 0 for sub images. */ |
||
818 | img->dri_components = 0; |
||
819 | return img; |
||
820 | } |
||
821 | |||
822 | static void |
||
823 | dri2_destroy_image(__DRIimage *img) |
||
824 | { |
||
825 | pipe_resource_reference(&img->texture, NULL); |
||
826 | FREE(img); |
||
827 | } |
||
828 | |||
829 | static struct __DRIimageExtensionRec dri2ImageExtension = { |
||
830 | { __DRI_IMAGE, 5 }, |
||
831 | dri2_create_image_from_name, |
||
832 | dri2_create_image_from_renderbuffer, |
||
833 | dri2_destroy_image, |
||
834 | dri2_create_image, |
||
835 | dri2_query_image, |
||
836 | dri2_dup_image, |
||
837 | dri2_validate_usage, |
||
838 | dri2_from_names, |
||
839 | dri2_from_planar, |
||
840 | }; |
||
841 | |||
842 | /* |
||
843 | * Backend function init_screen. |
||
844 | */ |
||
845 | |||
846 | static const __DRIextension *dri_screen_extensions[] = { |
||
847 | &driTexBufferExtension.base, |
||
848 | &dri2FlushExtension.base, |
||
849 | &dri2ImageExtension.base, |
||
850 | &dri2ConfigQueryExtension.base, |
||
851 | &dri2ThrottleExtension.base, |
||
852 | NULL |
||
853 | }; |
||
854 | |||
855 | /** |
||
856 | * This is the driver specific part of the createNewScreen entry point. |
||
857 | * |
||
858 | * Returns the struct gl_config supported by this driver. |
||
859 | */ |
||
860 | static const __DRIconfig ** |
||
861 | dri2_init_screen(__DRIscreen * sPriv) |
||
862 | { |
||
863 | const __DRIconfig **configs; |
||
864 | struct dri_screen *screen; |
||
865 | struct pipe_screen *pscreen; |
||
866 | const struct drm_conf_ret *throttle_ret = NULL; |
||
867 | |||
868 | screen = CALLOC_STRUCT(dri_screen); |
||
869 | if (!screen) |
||
870 | return NULL; |
||
871 | |||
872 | screen->sPriv = sPriv; |
||
873 | screen->fd = sPriv->fd; |
||
874 | |||
875 | sPriv->driverPrivate = (void *)screen; |
||
876 | |||
877 | pscreen = driver_descriptor.create_screen(screen->fd); |
||
878 | if (driver_descriptor.configuration) |
||
879 | throttle_ret = driver_descriptor.configuration(DRM_CONF_THROTTLE); |
||
880 | |||
881 | if (throttle_ret && throttle_ret->val.val_int != -1) { |
||
882 | screen->throttling_enabled = TRUE; |
||
883 | screen->default_throttle_frames = throttle_ret->val.val_int; |
||
884 | } |
||
885 | |||
886 | sPriv->extensions = dri_screen_extensions; |
||
887 | |||
888 | /* dri_init_screen_helper checks pscreen for us */ |
||
889 | |||
890 | configs = dri_init_screen_helper(screen, pscreen); |
||
891 | if (!configs) |
||
892 | goto fail; |
||
893 | |||
894 | sPriv->api_mask = 0; |
||
895 | if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK) |
||
896 | sPriv->api_mask |= 1 << __DRI_API_OPENGL; |
||
897 | if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK) |
||
898 | sPriv->api_mask |= 1 << __DRI_API_GLES; |
||
899 | if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK) |
||
900 | sPriv->api_mask |= 1 << __DRI_API_GLES2; |
||
901 | |||
902 | screen->auto_fake_front = dri_with_format(sPriv); |
||
903 | screen->broken_invalidate = !sPriv->dri2.useInvalidate; |
||
904 | screen->lookup_egl_image = dri2_lookup_egl_image; |
||
905 | |||
906 | return configs; |
||
907 | fail: |
||
908 | dri_destroy_screen_helper(screen); |
||
909 | FREE(screen); |
||
910 | return NULL; |
||
911 | } |
||
912 | |||
913 | static boolean |
||
914 | dri2_create_buffer(__DRIscreen * sPriv, |
||
915 | __DRIdrawable * dPriv, |
||
916 | const struct gl_config * visual, boolean isPixmap) |
||
917 | { |
||
918 | struct dri_drawable *drawable = NULL; |
||
919 | |||
920 | if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) |
||
921 | return FALSE; |
||
922 | |||
923 | drawable = dPriv->driverPrivate; |
||
924 | |||
925 | drawable->allocate_textures = dri2_allocate_textures; |
||
926 | drawable->flush_frontbuffer = dri2_flush_frontbuffer; |
||
927 | drawable->update_tex_buffer = dri2_update_tex_buffer; |
||
928 | |||
929 | return TRUE; |
||
930 | } |
||
931 | |||
932 | /** |
||
933 | * DRI driver virtual function table. |
||
934 | * |
||
935 | * DRI versions differ in their implementation of init_screen and swap_buffers. |
||
936 | */ |
||
937 | const struct __DriverAPIRec driDriverAPI = { |
||
938 | .InitScreen = dri2_init_screen, |
||
939 | .DestroyScreen = dri_destroy_screen, |
||
940 | .CreateContext = dri_create_context, |
||
941 | .DestroyContext = dri_destroy_context, |
||
942 | .CreateBuffer = dri2_create_buffer, |
||
943 | .DestroyBuffer = dri_destroy_buffer, |
||
944 | .MakeCurrent = dri_make_current, |
||
945 | .UnbindContext = dri_unbind_context, |
||
946 | |||
947 | .AllocateBuffer = dri2_allocate_buffer, |
||
948 | .ReleaseBuffer = dri2_release_buffer, |
||
949 | }; |
||
950 | |||
951 | /* This is the table of extensions that the loader will dlsym() for. */ |
||
952 | PUBLIC const __DRIextension *__driDriverExtensions[] = { |
||
953 | &driCoreExtension.base, |
||
954 | &driDRI2Extension.base, |
||
955 | NULL |
||
956 | }; |
||
957 | |||
958 | /* vim: set sw=3 ts=8 sts=3 expandtab: */><>><>><>>>>>>>> |