2 * Copyright (c) 2013 Brian Paul All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 * Off-Screen rendering into client memory.
26 * OpenGL gallium frontend for softpipe and llvmpipe.
30 * If Gallium is built with LLVM support we use the llvmpipe driver.
31 * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable
32 * may be set to "softpipe" or "llvmpipe" to override.
34 * With softpipe we could render directly into the user's buffer by using a
35 * display target resource. However, softpipe doesn't support "upside-down"
36 * rendering which would be needed for the OSMESA_Y_UP=TRUE case.
38 * With llvmpipe we could only render directly into the user's buffer when its
39 * width and height is a multiple of the tile size (64 pixels).
41 * Because of these constraints we always render into ordinary resources then
42 * copy the results to the user's buffer in the flush_front() function which
43 * is called when the app calls glFlush/Finish.
45 * In general, the OSMesa interface is pretty ugly and not a good match
46 * for Gallium. But we're interested in doing the best we can to preserve
47 * application portability. With a little work we could come up with a
48 * much nicer, new off-screen Gallium interface...
53 #include <c11/threads.h>
54 #include "GL/osmesa.h"
56 #include "glapi/glapi.h" /* for OSMesaGetProcAddress below */
58 #include "pipe/p_context.h"
59 #include "pipe/p_screen.h"
60 #include "pipe/p_state.h"
62 #include "util/u_atomic.h"
63 #include "util/u_box.h"
64 #include "util/u_debug.h"
65 #include "util/format/u_format.h"
66 #include "util/u_inlines.h"
67 #include "util/u_memory.h"
69 #include "postprocess/filters.h"
70 #include "postprocess/postprocess.h"
72 #include "frontend/api.h"
73 #include "state_tracker/st_gl_api.h"
77 extern struct pipe_screen
*
78 osmesa_create_screen(void);
84 struct st_framebuffer_iface
*stfb
;
85 struct st_visual visual
;
86 unsigned width
, height
;
88 struct pipe_resource
*textures
[ST_ATTACHMENT_COUNT
];
92 struct osmesa_buffer
*next
; /**< next in linked list */
98 struct st_context_iface
*stctx
;
100 boolean ever_used
; /*< Has this context ever been current? */
102 struct osmesa_buffer
*current_buffer
;
104 enum pipe_format depth_stencil_format
, accum_format
;
106 GLenum format
; /*< User-specified context format */
107 GLenum type
; /*< Buffer's data type */
108 GLint user_row_length
; /*< user-specified number of pixels per row */
109 GLboolean y_up
; /*< TRUE -> Y increases upward */
110 /*< FALSE -> Y increases downward */
112 /** Which postprocessing filters are enabled. */
113 unsigned pp_enabled
[PP_FILTERS
];
114 struct pp_queue_t
*pp
;
119 * Linked list of all osmesa_buffers.
120 * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to
121 * the next unless the color/depth/stencil/accum formats change.
122 * We have to do this to be compatible with the original OSMesa implementation
123 * because some apps call OSMesaMakeCurrent() several times during rendering
126 static struct osmesa_buffer
*BufferList
= NULL
;
130 * Called from the ST manager.
133 osmesa_st_get_param(struct st_manager
*smapi
, enum st_manager_param param
)
141 * Create/return singleton st_api object.
143 static struct st_api
*
146 static struct st_api
*stapi
= NULL
;
148 stapi
= st_gl_api_create();
153 static struct st_manager
*stmgr
= NULL
;
156 create_st_manager(void)
158 stmgr
= CALLOC_STRUCT(st_manager
);
160 stmgr
->screen
= osmesa_create_screen();
161 stmgr
->get_param
= osmesa_st_get_param
;
162 stmgr
->get_egl_image
= NULL
;
167 * Create/return a singleton st_manager object.
169 static struct st_manager
*
172 static once_flag create_once_flag
= ONCE_FLAG_INIT
;
174 call_once(&create_once_flag
, create_st_manager
);
181 * Given an OSMESA_x format and a GL_y type, return the best
182 * matching PIPE_FORMAT_z.
183 * Note that we can't exactly match all user format/type combinations
184 * with gallium formats. If we find this to be a problem, we can
185 * implement more elaborate format/type conversion in the flush_front()
188 static enum pipe_format
189 osmesa_choose_format(GLenum format
, GLenum type
)
193 if (type
== GL_UNSIGNED_BYTE
) {
194 #if UTIL_ARCH_LITTLE_ENDIAN
195 return PIPE_FORMAT_R8G8B8A8_UNORM
;
197 return PIPE_FORMAT_A8B8G8R8_UNORM
;
200 else if (type
== GL_UNSIGNED_SHORT
) {
201 return PIPE_FORMAT_R16G16B16A16_UNORM
;
203 else if (type
== GL_FLOAT
) {
204 return PIPE_FORMAT_R32G32B32A32_FLOAT
;
207 return PIPE_FORMAT_NONE
;
211 if (type
== GL_UNSIGNED_BYTE
) {
212 #if UTIL_ARCH_LITTLE_ENDIAN
213 return PIPE_FORMAT_B8G8R8A8_UNORM
;
215 return PIPE_FORMAT_A8R8G8B8_UNORM
;
218 else if (type
== GL_UNSIGNED_SHORT
) {
219 return PIPE_FORMAT_R16G16B16A16_UNORM
;
221 else if (type
== GL_FLOAT
) {
222 return PIPE_FORMAT_R32G32B32A32_FLOAT
;
225 return PIPE_FORMAT_NONE
;
229 if (type
== GL_UNSIGNED_BYTE
) {
230 #if UTIL_ARCH_LITTLE_ENDIAN
231 return PIPE_FORMAT_A8R8G8B8_UNORM
;
233 return PIPE_FORMAT_B8G8R8A8_UNORM
;
236 else if (type
== GL_UNSIGNED_SHORT
) {
237 return PIPE_FORMAT_R16G16B16A16_UNORM
;
239 else if (type
== GL_FLOAT
) {
240 return PIPE_FORMAT_R32G32B32A32_FLOAT
;
243 return PIPE_FORMAT_NONE
;
247 if (type
== GL_UNSIGNED_BYTE
) {
248 return PIPE_FORMAT_R8G8B8_UNORM
;
250 else if (type
== GL_UNSIGNED_SHORT
) {
251 return PIPE_FORMAT_R16G16B16_UNORM
;
253 else if (type
== GL_FLOAT
) {
254 return PIPE_FORMAT_R32G32B32_FLOAT
;
257 return PIPE_FORMAT_NONE
;
261 /* No gallium format for this one */
262 return PIPE_FORMAT_NONE
;
264 if (type
!= GL_UNSIGNED_SHORT_5_6_5
)
265 return PIPE_FORMAT_NONE
;
266 return PIPE_FORMAT_B5G6R5_UNORM
;
270 return PIPE_FORMAT_NONE
;
275 * Initialize an st_visual object.
278 osmesa_init_st_visual(struct st_visual
*vis
,
279 enum pipe_format color_format
,
280 enum pipe_format ds_format
,
281 enum pipe_format accum_format
)
283 vis
->buffer_mask
= ST_ATTACHMENT_FRONT_LEFT_MASK
;
285 if (ds_format
!= PIPE_FORMAT_NONE
)
286 vis
->buffer_mask
|= ST_ATTACHMENT_DEPTH_STENCIL_MASK
;
287 if (accum_format
!= PIPE_FORMAT_NONE
)
288 vis
->buffer_mask
|= ST_ATTACHMENT_ACCUM
;
290 vis
->color_format
= color_format
;
291 vis
->depth_stencil_format
= ds_format
;
292 vis
->accum_format
= accum_format
;
294 vis
->render_buffer
= ST_ATTACHMENT_FRONT_LEFT
;
299 * Return the osmesa_buffer that corresponds to an st_framebuffer_iface.
301 static inline struct osmesa_buffer
*
302 stfbi_to_osbuffer(struct st_framebuffer_iface
*stfbi
)
304 return (struct osmesa_buffer
*) stfbi
->st_manager_private
;
309 * Called via glFlush/glFinish. This is where we copy the contents
310 * of the driver's color buffer into the user-specified buffer.
313 osmesa_st_framebuffer_flush_front(struct st_context_iface
*stctx
,
314 struct st_framebuffer_iface
*stfbi
,
315 enum st_attachment_type statt
)
317 OSMesaContext osmesa
= OSMesaGetCurrentContext();
318 struct osmesa_buffer
*osbuffer
= stfbi_to_osbuffer(stfbi
);
319 struct pipe_context
*pipe
= stctx
->pipe
;
320 struct pipe_resource
*res
= osbuffer
->textures
[statt
];
321 struct pipe_transfer
*transfer
= NULL
;
325 unsigned y
, bytes
, bpp
;
329 struct pipe_resource
*zsbuf
= NULL
;
332 /* Find the z/stencil buffer if there is one */
333 for (i
= 0; i
< ARRAY_SIZE(osbuffer
->textures
); i
++) {
334 struct pipe_resource
*res
= osbuffer
->textures
[i
];
336 const struct util_format_description
*desc
=
337 util_format_description(res
->format
);
339 if (util_format_has_depth(desc
)) {
346 /* run the postprocess stage(s) */
347 pp_run(osmesa
->pp
, res
, res
, zsbuf
);
350 u_box_2d(0, 0, res
->width0
, res
->height0
, &box
);
352 map
= pipe
->transfer_map(pipe
, res
, 0, PIPE_TRANSFER_READ
, &box
,
356 * Copy the color buffer from the resource to the user's buffer.
358 bpp
= util_format_get_blocksize(osbuffer
->visual
.color_format
);
361 if (osmesa
->user_row_length
)
362 dst_stride
= bpp
* osmesa
->user_row_length
;
364 dst_stride
= bpp
* osbuffer
->width
;
365 bytes
= bpp
* res
->width0
;
368 /* need to flip image upside down */
369 dst
= dst
+ (res
->height0
- 1) * dst_stride
;
370 dst_stride
= -dst_stride
;
373 for (y
= 0; y
< res
->height0
; y
++) {
374 memcpy(dst
, src
, bytes
);
376 src
+= transfer
->stride
;
379 pipe
->transfer_unmap(pipe
, transfer
);
386 * Called by the st manager to validate the framebuffer (allocate
390 osmesa_st_framebuffer_validate(struct st_context_iface
*stctx
,
391 struct st_framebuffer_iface
*stfbi
,
392 const enum st_attachment_type
*statts
,
394 struct pipe_resource
**out
)
396 struct pipe_screen
*screen
= get_st_manager()->screen
;
397 enum st_attachment_type i
;
398 struct osmesa_buffer
*osbuffer
= stfbi_to_osbuffer(stfbi
);
399 struct pipe_resource templat
;
401 memset(&templat
, 0, sizeof(templat
));
402 templat
.target
= PIPE_TEXTURE_RECT
;
403 templat
.format
= 0; /* setup below */
404 templat
.last_level
= 0;
405 templat
.width0
= osbuffer
->width
;
406 templat
.height0
= osbuffer
->height
;
408 templat
.array_size
= 1;
409 templat
.usage
= PIPE_USAGE_DEFAULT
;
410 templat
.bind
= 0; /* setup below */
413 for (i
= 0; i
< count
; i
++) {
414 enum pipe_format format
= PIPE_FORMAT_NONE
;
418 * At this time, we really only need to handle the front-left color
419 * attachment, since that's all we specified for the visual in
420 * osmesa_init_st_visual().
422 if (statts
[i
] == ST_ATTACHMENT_FRONT_LEFT
) {
423 format
= osbuffer
->visual
.color_format
;
424 bind
= PIPE_BIND_RENDER_TARGET
;
426 else if (statts
[i
] == ST_ATTACHMENT_DEPTH_STENCIL
) {
427 format
= osbuffer
->visual
.depth_stencil_format
;
428 bind
= PIPE_BIND_DEPTH_STENCIL
;
430 else if (statts
[i
] == ST_ATTACHMENT_ACCUM
) {
431 format
= osbuffer
->visual
.accum_format
;
432 bind
= PIPE_BIND_RENDER_TARGET
;
435 debug_warning("Unexpected attachment type in "
436 "osmesa_st_framebuffer_validate()");
439 templat
.format
= format
;
441 pipe_resource_reference(&out
[i
], NULL
);
442 out
[i
] = osbuffer
->textures
[statts
[i
]] =
443 screen
->resource_create(screen
, &templat
);
449 static uint32_t osmesa_fb_ID
= 0;
451 static struct st_framebuffer_iface
*
452 osmesa_create_st_framebuffer(void)
454 struct st_framebuffer_iface
*stfbi
= CALLOC_STRUCT(st_framebuffer_iface
);
456 stfbi
->flush_front
= osmesa_st_framebuffer_flush_front
;
457 stfbi
->validate
= osmesa_st_framebuffer_validate
;
458 p_atomic_set(&stfbi
->stamp
, 1);
459 stfbi
->ID
= p_atomic_inc_return(&osmesa_fb_ID
);
460 stfbi
->state_manager
= get_st_manager();
467 * Create new buffer and add to linked list.
469 static struct osmesa_buffer
*
470 osmesa_create_buffer(enum pipe_format color_format
,
471 enum pipe_format ds_format
,
472 enum pipe_format accum_format
)
474 struct osmesa_buffer
*osbuffer
= CALLOC_STRUCT(osmesa_buffer
);
476 osbuffer
->stfb
= osmesa_create_st_framebuffer();
478 osbuffer
->stfb
->st_manager_private
= osbuffer
;
479 osbuffer
->stfb
->visual
= &osbuffer
->visual
;
481 osmesa_init_st_visual(&osbuffer
->visual
, color_format
,
482 ds_format
, accum_format
);
484 /* insert into linked list */
485 osbuffer
->next
= BufferList
;
486 BufferList
= osbuffer
;
494 * Search linked list for a buffer with matching pixel formats and size.
496 static struct osmesa_buffer
*
497 osmesa_find_buffer(enum pipe_format color_format
,
498 enum pipe_format ds_format
,
499 enum pipe_format accum_format
,
500 GLsizei width
, GLsizei height
)
502 struct osmesa_buffer
*b
;
504 /* Check if we already have a suitable buffer for the given formats */
505 for (b
= BufferList
; b
; b
= b
->next
) {
506 if (b
->visual
.color_format
== color_format
&&
507 b
->visual
.depth_stencil_format
== ds_format
&&
508 b
->visual
.accum_format
== accum_format
&&
510 b
->height
== height
) {
519 osmesa_destroy_buffer(struct osmesa_buffer
*osbuffer
)
521 struct st_api
*stapi
= get_st_api();
524 * Notify the state manager that the associated framebuffer interface
525 * is no longer valid.
527 stapi
->destroy_drawable(stapi
, osbuffer
->stfb
);
529 FREE(osbuffer
->stfb
);
535 /**********************************************************************/
536 /***** Public Functions *****/
537 /**********************************************************************/
541 * Create an Off-Screen Mesa rendering context. The only attribute needed is
542 * an RGBA vs Color-Index mode flag.
544 * Input: format - Must be GL_RGBA
545 * sharelist - specifies another OSMesaContext with which to share
546 * display lists. NULL indicates no sharing.
547 * Return: an OSMesaContext or 0 if error
549 GLAPI OSMesaContext GLAPIENTRY
550 OSMesaCreateContext(GLenum format
, OSMesaContext sharelist
)
552 return OSMesaCreateContextExt(format
, 24, 8, 0, sharelist
);
559 * Create context and specify size of ancillary buffers.
561 GLAPI OSMesaContext GLAPIENTRY
562 OSMesaCreateContextExt(GLenum format
, GLint depthBits
, GLint stencilBits
,
563 GLint accumBits
, OSMesaContext sharelist
)
565 int attribs
[100], n
= 0;
567 attribs
[n
++] = OSMESA_FORMAT
;
568 attribs
[n
++] = format
;
569 attribs
[n
++] = OSMESA_DEPTH_BITS
;
570 attribs
[n
++] = depthBits
;
571 attribs
[n
++] = OSMESA_STENCIL_BITS
;
572 attribs
[n
++] = stencilBits
;
573 attribs
[n
++] = OSMESA_ACCUM_BITS
;
574 attribs
[n
++] = accumBits
;
577 return OSMesaCreateContextAttribs(attribs
, sharelist
);
584 * Create context with attribute list.
586 GLAPI OSMesaContext GLAPIENTRY
587 OSMesaCreateContextAttribs(const int *attribList
, OSMesaContext sharelist
)
589 OSMesaContext osmesa
;
590 struct st_context_iface
*st_shared
;
591 enum st_context_error st_error
= 0;
592 struct st_context_attribs attribs
;
593 struct st_api
*stapi
= get_st_api();
594 GLenum format
= GL_RGBA
;
595 int depthBits
= 0, stencilBits
= 0, accumBits
= 0;
596 int profile
= OSMESA_COMPAT_PROFILE
, version_major
= 1, version_minor
= 0;
600 st_shared
= sharelist
->stctx
;
606 for (i
= 0; attribList
[i
]; i
+= 2) {
607 switch (attribList
[i
]) {
609 format
= attribList
[i
+1];
611 case OSMESA_COLOR_INDEX
:
624 case OSMESA_DEPTH_BITS
:
625 depthBits
= attribList
[i
+1];
629 case OSMESA_STENCIL_BITS
:
630 stencilBits
= attribList
[i
+1];
634 case OSMESA_ACCUM_BITS
:
635 accumBits
= attribList
[i
+1];
640 profile
= attribList
[i
+1];
641 if (profile
!= OSMESA_CORE_PROFILE
&&
642 profile
!= OSMESA_COMPAT_PROFILE
)
645 case OSMESA_CONTEXT_MAJOR_VERSION
:
646 version_major
= attribList
[i
+1];
647 if (version_major
< 1)
650 case OSMESA_CONTEXT_MINOR_VERSION
:
651 version_minor
= attribList
[i
+1];
652 if (version_minor
< 0)
659 fprintf(stderr
, "Bad attribute in OSMesaCreateContextAttribs()\n");
664 osmesa
= (OSMesaContext
) CALLOC_STRUCT(osmesa_context
);
668 /* Choose depth/stencil/accum buffer formats */
670 osmesa
->accum_format
= PIPE_FORMAT_R16G16B16A16_SNORM
;
672 if (depthBits
> 0 && stencilBits
> 0) {
673 osmesa
->depth_stencil_format
= PIPE_FORMAT_Z24_UNORM_S8_UINT
;
675 else if (stencilBits
> 0) {
676 osmesa
->depth_stencil_format
= PIPE_FORMAT_S8_UINT
;
678 else if (depthBits
>= 24) {
679 osmesa
->depth_stencil_format
= PIPE_FORMAT_Z24X8_UNORM
;
681 else if (depthBits
>= 16) {
682 osmesa
->depth_stencil_format
= PIPE_FORMAT_Z16_UNORM
;
686 * Create the rendering context
688 memset(&attribs
, 0, sizeof(attribs
));
689 attribs
.profile
= (profile
== OSMESA_CORE_PROFILE
)
690 ? ST_PROFILE_OPENGL_CORE
: ST_PROFILE_DEFAULT
;
691 attribs
.major
= version_major
;
692 attribs
.minor
= version_minor
;
693 attribs
.flags
= 0; /* ST_CONTEXT_FLAG_x */
694 attribs
.options
.force_glsl_extensions_warn
= FALSE
;
695 attribs
.options
.disable_blend_func_extended
= FALSE
;
696 attribs
.options
.disable_glsl_line_continuations
= FALSE
;
697 attribs
.options
.force_glsl_version
= 0;
699 osmesa_init_st_visual(&attribs
.visual
,
701 osmesa
->depth_stencil_format
,
702 osmesa
->accum_format
);
704 osmesa
->stctx
= stapi
->create_context(stapi
, get_st_manager(),
705 &attribs
, &st_error
, st_shared
);
706 if (!osmesa
->stctx
) {
711 osmesa
->stctx
->st_manager_private
= osmesa
;
713 osmesa
->format
= format
;
714 osmesa
->user_row_length
= 0;
715 osmesa
->y_up
= GL_TRUE
;
723 * Destroy an Off-Screen Mesa rendering context.
725 * \param osmesa the context to destroy
727 GLAPI
void GLAPIENTRY
728 OSMesaDestroyContext(OSMesaContext osmesa
)
732 osmesa
->stctx
->destroy(osmesa
->stctx
);
739 * Bind an OSMesaContext to an image buffer. The image buffer is just a
740 * block of memory which the client provides. Its size must be at least
741 * as large as width*height*pixelSize. Its address should be a multiple
742 * of 4 if using RGBA mode.
744 * By default, image data is stored in the order of glDrawPixels: row-major
745 * order with the lower-left image pixel stored in the first array position
746 * (ie. bottom-to-top).
748 * If the context's viewport hasn't been initialized yet, it will now be
749 * initialized to (0,0,width,height).
751 * Input: osmesa - the rendering context
752 * buffer - the image buffer memory
753 * type - data type for pixel components
754 * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT
756 * width, height - size of image buffer in pixels, at least 1
757 * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
758 * invalid type, invalid size, etc.
760 GLAPI GLboolean GLAPIENTRY
761 OSMesaMakeCurrent(OSMesaContext osmesa
, void *buffer
, GLenum type
,
762 GLsizei width
, GLsizei height
)
764 struct st_api
*stapi
= get_st_api();
765 struct osmesa_buffer
*osbuffer
;
766 enum pipe_format color_format
;
768 if (!osmesa
&& !buffer
) {
769 stapi
->make_current(stapi
, NULL
, NULL
, NULL
);
773 if (!osmesa
|| !buffer
|| width
< 1 || height
< 1) {
777 color_format
= osmesa_choose_format(osmesa
->format
, type
);
778 if (color_format
== PIPE_FORMAT_NONE
) {
779 fprintf(stderr
, "OSMesaMakeCurrent(unsupported format/type)\n");
783 /* See if we already have a buffer that uses these pixel formats */
784 osbuffer
= osmesa_find_buffer(color_format
,
785 osmesa
->depth_stencil_format
,
786 osmesa
->accum_format
, width
, height
);
788 /* Existing buffer found, create new buffer */
789 osbuffer
= osmesa_create_buffer(color_format
,
790 osmesa
->depth_stencil_format
,
791 osmesa
->accum_format
);
794 osbuffer
->width
= width
;
795 osbuffer
->height
= height
;
796 osbuffer
->map
= buffer
;
798 /* XXX unused for now */
799 (void) osmesa_destroy_buffer
;
801 osmesa
->current_buffer
= osbuffer
;
804 stapi
->make_current(stapi
, osmesa
->stctx
, osbuffer
->stfb
, osbuffer
->stfb
);
806 if (!osmesa
->ever_used
) {
807 /* one-time init, just postprocessing for now */
808 boolean any_pp_enabled
= FALSE
;
811 for (i
= 0; i
< ARRAY_SIZE(osmesa
->pp_enabled
); i
++) {
812 if (osmesa
->pp_enabled
[i
]) {
813 any_pp_enabled
= TRUE
;
818 if (any_pp_enabled
) {
819 osmesa
->pp
= pp_init(osmesa
->stctx
->pipe
,
821 osmesa
->stctx
->cso_context
);
823 pp_init_fbos(osmesa
->pp
, width
, height
);
826 osmesa
->ever_used
= TRUE
;
834 GLAPI OSMesaContext GLAPIENTRY
835 OSMesaGetCurrentContext(void)
837 struct st_api
*stapi
= get_st_api();
838 struct st_context_iface
*st
= stapi
->get_current(stapi
);
839 return st
? (OSMesaContext
) st
->st_manager_private
: NULL
;
844 GLAPI
void GLAPIENTRY
845 OSMesaPixelStore(GLint pname
, GLint value
)
847 OSMesaContext osmesa
= OSMesaGetCurrentContext();
850 case OSMESA_ROW_LENGTH
:
851 osmesa
->user_row_length
= value
;
854 osmesa
->y_up
= value
? GL_TRUE
: GL_FALSE
;
857 fprintf(stderr
, "Invalid pname in OSMesaPixelStore()\n");
863 GLAPI
void GLAPIENTRY
864 OSMesaGetIntegerv(GLint pname
, GLint
*value
)
866 OSMesaContext osmesa
= OSMesaGetCurrentContext();
867 struct osmesa_buffer
*osbuffer
= osmesa
? osmesa
->current_buffer
: NULL
;
871 *value
= osbuffer
? osbuffer
->width
: 0;
874 *value
= osbuffer
? osbuffer
->height
: 0;
877 *value
= osmesa
->format
;
880 /* current color buffer's data type */
881 *value
= osmesa
->type
;
883 case OSMESA_ROW_LENGTH
:
884 *value
= osmesa
->user_row_length
;
887 *value
= osmesa
->y_up
;
889 case OSMESA_MAX_WIDTH
:
891 case OSMESA_MAX_HEIGHT
:
893 struct pipe_screen
*screen
= get_st_manager()->screen
;
894 *value
= screen
->get_param(screen
, PIPE_CAP_MAX_TEXTURE_2D_SIZE
);
898 fprintf(stderr
, "Invalid pname in OSMesaGetIntegerv()\n");
905 * Return information about the depth buffer associated with an OSMesa context.
906 * Input: c - the OSMesa context
907 * Output: width, height - size of buffer in pixels
908 * bytesPerValue - bytes per depth value (2 or 4)
909 * buffer - pointer to depth buffer values
910 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
912 GLAPI GLboolean GLAPIENTRY
913 OSMesaGetDepthBuffer(OSMesaContext c
, GLint
*width
, GLint
*height
,
914 GLint
*bytesPerValue
, void **buffer
)
916 struct osmesa_buffer
*osbuffer
= c
->current_buffer
;
917 struct pipe_context
*pipe
= c
->stctx
->pipe
;
918 struct pipe_resource
*res
= osbuffer
->textures
[ST_ATTACHMENT_DEPTH_STENCIL
];
919 struct pipe_transfer
*transfer
= NULL
;
923 * Note: we can't really implement this function with gallium as
924 * we did for swrast. We can't just map the resource and leave it
925 * mapped (and there's no OSMesaUnmapDepthBuffer() function) so
926 * we unmap the buffer here and return a 'stale' pointer. This should
927 * actually be OK in most cases where the caller of this function
928 * immediately uses the pointer.
931 u_box_2d(0, 0, res
->width0
, res
->height0
, &box
);
933 *buffer
= pipe
->transfer_map(pipe
, res
, 0, PIPE_TRANSFER_READ
, &box
,
939 *width
= res
->width0
;
940 *height
= res
->height0
;
941 *bytesPerValue
= util_format_get_blocksize(res
->format
);
943 pipe
->transfer_unmap(pipe
, transfer
);
950 * Return the color buffer associated with an OSMesa context.
951 * Input: c - the OSMesa context
952 * Output: width, height - size of buffer in pixels
953 * format - the pixel format (OSMESA_FORMAT)
954 * buffer - pointer to color buffer values
955 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
957 GLAPI GLboolean GLAPIENTRY
958 OSMesaGetColorBuffer(OSMesaContext osmesa
, GLint
*width
,
959 GLint
*height
, GLint
*format
, void **buffer
)
961 struct osmesa_buffer
*osbuffer
= osmesa
->current_buffer
;
964 *width
= osbuffer
->width
;
965 *height
= osbuffer
->height
;
966 *format
= osmesa
->format
;
967 *buffer
= osbuffer
->map
;
986 static struct name_function functions
[] = {
987 { "OSMesaCreateContext", (OSMESAproc
) OSMesaCreateContext
},
988 { "OSMesaCreateContextExt", (OSMESAproc
) OSMesaCreateContextExt
},
989 { "OSMesaCreateContextAttribs", (OSMESAproc
) OSMesaCreateContextAttribs
},
990 { "OSMesaDestroyContext", (OSMESAproc
) OSMesaDestroyContext
},
991 { "OSMesaMakeCurrent", (OSMESAproc
) OSMesaMakeCurrent
},
992 { "OSMesaGetCurrentContext", (OSMESAproc
) OSMesaGetCurrentContext
},
993 { "OSMesaPixelStore", (OSMESAproc
) OSMesaPixelStore
},
994 { "OSMesaGetIntegerv", (OSMESAproc
) OSMesaGetIntegerv
},
995 { "OSMesaGetDepthBuffer", (OSMESAproc
) OSMesaGetDepthBuffer
},
996 { "OSMesaGetColorBuffer", (OSMESAproc
) OSMesaGetColorBuffer
},
997 { "OSMesaGetProcAddress", (OSMESAproc
) OSMesaGetProcAddress
},
998 { "OSMesaColorClamp", (OSMESAproc
) OSMesaColorClamp
},
999 { "OSMesaPostprocess", (OSMESAproc
) OSMesaPostprocess
},
1004 GLAPI OSMESAproc GLAPIENTRY
1005 OSMesaGetProcAddress(const char *funcName
)
1008 for (i
= 0; functions
[i
].Name
; i
++) {
1009 if (strcmp(functions
[i
].Name
, funcName
) == 0)
1010 return functions
[i
].Function
;
1012 return _glapi_get_proc_address(funcName
);
1016 GLAPI
void GLAPIENTRY
1017 OSMesaColorClamp(GLboolean enable
)
1019 extern void GLAPIENTRY
_mesa_ClampColor(GLenum target
, GLenum clamp
);
1021 _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB
,
1022 enable
? GL_TRUE
: GL_FIXED_ONLY_ARB
);
1026 GLAPI
void GLAPIENTRY
1027 OSMesaPostprocess(OSMesaContext osmesa
, const char *filter
,
1028 unsigned enable_value
)
1030 if (!osmesa
->ever_used
) {
1031 /* We can only enable/disable postprocess filters before a context
1032 * is made current for the first time.
1036 for (i
= 0; i
< PP_FILTERS
; i
++) {
1037 if (strcmp(pp_filters
[i
].name
, filter
) == 0) {
1038 osmesa
->pp_enabled
[i
] = enable_value
;
1042 debug_warning("OSMesaPostprocess(unknown filter)\n");
1045 debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n");