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
/* Storage for depth/stencil, if the user has requested access. The backing
105
* driver always has its own storage for the actual depth/stencil, which we
106
* have to transfer in and out.
111
enum pipe_format depth_stencil_format, accum_format;
113
GLenum format; /*< User-specified context format */
114
GLenum type; /*< Buffer's data type */
115
GLint user_row_length; /*< user-specified number of pixels per row */
116
GLboolean y_up; /*< TRUE -> Y increases upward */
117
/*< FALSE -> Y increases downward */
119
/** Which postprocessing filters are enabled. */
120
unsigned pp_enabled[PP_FILTERS];
121
struct pp_queue_t *pp;
125
* Called from the ST manager.
128
osmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param)
134
static struct st_manager *stmgr = NULL;
135
static struct st_api *stapi = NULL;
138
destroy_st_manager(void)
142
stmgr->screen->destroy(stmgr->screen);
146
if (stapi && stapi->destroy) {
147
stapi->destroy(stapi);
152
create_st_manager(void)
154
if (atexit(destroy_st_manager) != 0)
157
stmgr = CALLOC_STRUCT(st_manager);
159
stmgr->screen = osmesa_create_screen();
160
stmgr->get_param = osmesa_st_get_param;
161
stmgr->get_egl_image = NULL;
164
stapi = st_gl_api_create();
168
* Create/return a singleton st_manager object.
170
static struct st_manager *
173
static once_flag create_once_flag = ONCE_FLAG_INIT;
175
call_once(&create_once_flag, create_st_manager);
181
* Create/return singleton st_api object.
183
static struct st_api *
190
/* Reads the color or depth buffer from the backing context to either the user storage
191
* (color buffer) or our temporary (z/s)
194
osmesa_read_buffer(OSMesaContext osmesa, struct pipe_resource *res, void *dst,
195
int dst_stride, bool y_up)
197
struct pipe_context *pipe = osmesa->stctx->pipe;
200
u_box_2d(0, 0, res->width0, res->height0, &box);
202
struct pipe_transfer *transfer = NULL;
203
ubyte *src = pipe->texture_map(pipe, res, 0, PIPE_MAP_READ, &box,
207
* Copy the color buffer from the resource to the user's buffer.
211
/* need to flip image upside down */
212
dst = (ubyte *)dst + (res->height0 - 1) * dst_stride;
213
dst_stride = -dst_stride;
216
unsigned bpp = util_format_get_blocksize(res->format);
217
for (unsigned y = 0; y < res->height0; y++)
219
memcpy(dst, src, bpp * res->width0);
220
dst = (ubyte *)dst + dst_stride;
221
src += transfer->stride;
224
pipe->texture_unmap(pipe, transfer);
229
* Given an OSMESA_x format and a GL_y type, return the best
230
* matching PIPE_FORMAT_z.
231
* Note that we can't exactly match all user format/type combinations
232
* with gallium formats. If we find this to be a problem, we can
233
* implement more elaborate format/type conversion in the flush_front()
236
static enum pipe_format
237
osmesa_choose_format(GLenum format, GLenum type)
241
if (type == GL_UNSIGNED_BYTE) {
242
#if UTIL_ARCH_LITTLE_ENDIAN
243
return PIPE_FORMAT_R8G8B8A8_UNORM;
245
return PIPE_FORMAT_A8B8G8R8_UNORM;
248
else if (type == GL_UNSIGNED_SHORT) {
249
return PIPE_FORMAT_R16G16B16A16_UNORM;
251
else if (type == GL_FLOAT) {
252
return PIPE_FORMAT_R32G32B32A32_FLOAT;
255
return PIPE_FORMAT_NONE;
259
if (type == GL_UNSIGNED_BYTE) {
260
#if UTIL_ARCH_LITTLE_ENDIAN
261
return PIPE_FORMAT_B8G8R8A8_UNORM;
263
return PIPE_FORMAT_A8R8G8B8_UNORM;
266
else if (type == GL_UNSIGNED_SHORT) {
267
return PIPE_FORMAT_R16G16B16A16_UNORM;
269
else if (type == GL_FLOAT) {
270
return PIPE_FORMAT_R32G32B32A32_FLOAT;
273
return PIPE_FORMAT_NONE;
277
if (type == GL_UNSIGNED_BYTE) {
278
#if UTIL_ARCH_LITTLE_ENDIAN
279
return PIPE_FORMAT_A8R8G8B8_UNORM;
281
return PIPE_FORMAT_B8G8R8A8_UNORM;
284
else if (type == GL_UNSIGNED_SHORT) {
285
return PIPE_FORMAT_R16G16B16A16_UNORM;
287
else if (type == GL_FLOAT) {
288
return PIPE_FORMAT_R32G32B32A32_FLOAT;
291
return PIPE_FORMAT_NONE;
295
if (type == GL_UNSIGNED_BYTE) {
296
return PIPE_FORMAT_R8G8B8_UNORM;
298
else if (type == GL_UNSIGNED_SHORT) {
299
return PIPE_FORMAT_R16G16B16_UNORM;
301
else if (type == GL_FLOAT) {
302
return PIPE_FORMAT_R32G32B32_FLOAT;
305
return PIPE_FORMAT_NONE;
309
/* No gallium format for this one */
310
return PIPE_FORMAT_NONE;
312
if (type != GL_UNSIGNED_SHORT_5_6_5)
313
return PIPE_FORMAT_NONE;
314
return PIPE_FORMAT_B5G6R5_UNORM;
316
return PIPE_FORMAT_NONE;
322
* Initialize an st_visual object.
325
osmesa_init_st_visual(struct st_visual *vis,
326
enum pipe_format color_format,
327
enum pipe_format ds_format,
328
enum pipe_format accum_format)
330
vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
332
if (ds_format != PIPE_FORMAT_NONE)
333
vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
334
if (accum_format != PIPE_FORMAT_NONE)
335
vis->buffer_mask |= ST_ATTACHMENT_ACCUM;
337
vis->color_format = color_format;
338
vis->depth_stencil_format = ds_format;
339
vis->accum_format = accum_format;
345
* Return the osmesa_buffer that corresponds to an st_framebuffer_iface.
347
static inline struct osmesa_buffer *
348
stfbi_to_osbuffer(struct st_framebuffer_iface *stfbi)
350
return (struct osmesa_buffer *) stfbi->st_manager_private;
355
* Called via glFlush/glFinish. This is where we copy the contents
356
* of the driver's color buffer into the user-specified buffer.
359
osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx,
360
struct st_framebuffer_iface *stfbi,
361
enum st_attachment_type statt)
363
OSMesaContext osmesa = OSMesaGetCurrentContext();
364
struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
365
struct pipe_resource *res = osbuffer->textures[statt];
369
if (statt != ST_ATTACHMENT_FRONT_LEFT)
373
struct pipe_resource *zsbuf = NULL;
376
/* Find the z/stencil buffer if there is one */
377
for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) {
378
struct pipe_resource *res = osbuffer->textures[i];
380
const struct util_format_description *desc =
381
util_format_description(res->format);
383
if (util_format_has_depth(desc)) {
390
/* run the postprocess stage(s) */
391
pp_run(osmesa->pp, res, res, zsbuf);
394
/* Snapshot the color buffer to the user's buffer. */
395
bpp = util_format_get_blocksize(osbuffer->visual.color_format);
396
if (osmesa->user_row_length)
397
dst_stride = bpp * osmesa->user_row_length;
399
dst_stride = bpp * osbuffer->width;
401
osmesa_read_buffer(osmesa, res, osbuffer->map, dst_stride, osmesa->y_up);
403
/* If the user has requested the Z/S buffer, then snapshot that one too. */
405
osmesa_read_buffer(osmesa, osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL],
406
osmesa->zs, osmesa->zs_stride, true);
414
* Called by the st manager to validate the framebuffer (allocate
418
osmesa_st_framebuffer_validate(struct st_context_iface *stctx,
419
struct st_framebuffer_iface *stfbi,
420
const enum st_attachment_type *statts,
422
struct pipe_resource **out)
424
struct pipe_screen *screen = get_st_manager()->screen;
425
enum st_attachment_type i;
426
struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
427
struct pipe_resource templat;
429
memset(&templat, 0, sizeof(templat));
430
templat.target = PIPE_TEXTURE_RECT;
431
templat.format = 0; /* setup below */
432
templat.last_level = 0;
433
templat.width0 = osbuffer->width;
434
templat.height0 = osbuffer->height;
436
templat.array_size = 1;
437
templat.usage = PIPE_USAGE_DEFAULT;
438
templat.bind = 0; /* setup below */
441
for (i = 0; i < count; i++) {
442
enum pipe_format format = PIPE_FORMAT_NONE;
446
* At this time, we really only need to handle the front-left color
447
* attachment, since that's all we specified for the visual in
448
* osmesa_init_st_visual().
450
if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
451
format = osbuffer->visual.color_format;
452
bind = PIPE_BIND_RENDER_TARGET;
454
else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
455
format = osbuffer->visual.depth_stencil_format;
456
bind = PIPE_BIND_DEPTH_STENCIL;
458
else if (statts[i] == ST_ATTACHMENT_ACCUM) {
459
format = osbuffer->visual.accum_format;
460
bind = PIPE_BIND_RENDER_TARGET;
463
debug_warning("Unexpected attachment type in "
464
"osmesa_st_framebuffer_validate()");
467
templat.format = format;
469
pipe_resource_reference(&out[i], NULL);
470
out[i] = osbuffer->textures[statts[i]] =
471
screen->resource_create(screen, &templat);
477
static uint32_t osmesa_fb_ID = 0;
479
static struct st_framebuffer_iface *
480
osmesa_create_st_framebuffer(void)
482
struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface);
484
stfbi->flush_front = osmesa_st_framebuffer_flush_front;
485
stfbi->validate = osmesa_st_framebuffer_validate;
486
p_atomic_set(&stfbi->stamp, 1);
487
stfbi->ID = p_atomic_inc_return(&osmesa_fb_ID);
488
stfbi->state_manager = get_st_manager();
495
* Create new buffer and add to linked list.
497
static struct osmesa_buffer *
498
osmesa_create_buffer(enum pipe_format color_format,
499
enum pipe_format ds_format,
500
enum pipe_format accum_format)
502
struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer);
504
osbuffer->stfb = osmesa_create_st_framebuffer();
506
osbuffer->stfb->st_manager_private = osbuffer;
507
osbuffer->stfb->visual = &osbuffer->visual;
509
osmesa_init_st_visual(&osbuffer->visual, color_format,
510
ds_format, accum_format);
518
osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
521
* Notify the state manager that the associated framebuffer interface
522
* is no longer valid.
524
stapi->destroy_drawable(stapi, osbuffer->stfb);
526
FREE(osbuffer->stfb);
532
/**********************************************************************/
533
/***** Public Functions *****/
534
/**********************************************************************/
538
* Create an Off-Screen Mesa rendering context. The only attribute needed is
539
* an RGBA vs Color-Index mode flag.
541
* Input: format - Must be GL_RGBA
542
* sharelist - specifies another OSMesaContext with which to share
543
* display lists. NULL indicates no sharing.
544
* Return: an OSMesaContext or 0 if error
546
GLAPI OSMesaContext GLAPIENTRY
547
OSMesaCreateContext(GLenum format, OSMesaContext sharelist)
549
return OSMesaCreateContextExt(format, 24, 8, 0, sharelist);
556
* Create context and specify size of ancillary buffers.
558
GLAPI OSMesaContext GLAPIENTRY
559
OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits,
560
GLint accumBits, OSMesaContext sharelist)
562
int attribs[100], n = 0;
564
attribs[n++] = OSMESA_FORMAT;
565
attribs[n++] = format;
566
attribs[n++] = OSMESA_DEPTH_BITS;
567
attribs[n++] = depthBits;
568
attribs[n++] = OSMESA_STENCIL_BITS;
569
attribs[n++] = stencilBits;
570
attribs[n++] = OSMESA_ACCUM_BITS;
571
attribs[n++] = accumBits;
574
return OSMesaCreateContextAttribs(attribs, sharelist);
581
* Create context with attribute list.
583
GLAPI OSMesaContext GLAPIENTRY
584
OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
586
OSMesaContext osmesa;
587
struct st_context_iface *st_shared;
588
enum st_context_error st_error = 0;
589
struct st_context_attribs attribs;
590
struct st_api *stapi = get_st_api();
591
GLenum format = GL_RGBA;
592
int depthBits = 0, stencilBits = 0, accumBits = 0;
593
int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0;
597
st_shared = sharelist->stctx;
603
for (i = 0; attribList[i]; i += 2) {
604
switch (attribList[i]) {
606
format = attribList[i+1];
608
case OSMESA_COLOR_INDEX:
621
case OSMESA_DEPTH_BITS:
622
depthBits = attribList[i+1];
626
case OSMESA_STENCIL_BITS:
627
stencilBits = attribList[i+1];
631
case OSMESA_ACCUM_BITS:
632
accumBits = attribList[i+1];
637
profile = attribList[i+1];
638
if (profile != OSMESA_CORE_PROFILE &&
639
profile != OSMESA_COMPAT_PROFILE)
642
case OSMESA_CONTEXT_MAJOR_VERSION:
643
version_major = attribList[i+1];
644
if (version_major < 1)
647
case OSMESA_CONTEXT_MINOR_VERSION:
648
version_minor = attribList[i+1];
649
if (version_minor < 0)
656
fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n");
661
osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
665
/* Choose depth/stencil/accum buffer formats */
667
osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM;
669
if (depthBits > 0 && stencilBits > 0) {
670
osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
672
else if (stencilBits > 0) {
673
osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT;
675
else if (depthBits >= 24) {
676
osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
678
else if (depthBits >= 16) {
679
osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
683
* Create the rendering context
685
memset(&attribs, 0, sizeof(attribs));
686
attribs.profile = (profile == OSMESA_CORE_PROFILE)
687
? ST_PROFILE_OPENGL_CORE : ST_PROFILE_DEFAULT;
688
attribs.major = version_major;
689
attribs.minor = version_minor;
690
attribs.flags = 0; /* ST_CONTEXT_FLAG_x */
691
attribs.options.force_glsl_extensions_warn = FALSE;
692
attribs.options.disable_blend_func_extended = FALSE;
693
attribs.options.disable_glsl_line_continuations = FALSE;
694
attribs.options.force_glsl_version = 0;
696
osmesa_init_st_visual(&attribs.visual,
698
osmesa->depth_stencil_format,
699
osmesa->accum_format);
701
osmesa->stctx = stapi->create_context(stapi, get_st_manager(),
702
&attribs, &st_error, st_shared);
703
if (!osmesa->stctx) {
708
osmesa->stctx->st_manager_private = osmesa;
710
osmesa->format = format;
711
osmesa->user_row_length = 0;
712
osmesa->y_up = GL_TRUE;
720
* Destroy an Off-Screen Mesa rendering context.
722
* \param osmesa the context to destroy
724
GLAPI void GLAPIENTRY
725
OSMesaDestroyContext(OSMesaContext osmesa)
729
osmesa->stctx->destroy(osmesa->stctx);
737
* Bind an OSMesaContext to an image buffer. The image buffer is just a
738
* block of memory which the client provides. Its size must be at least
739
* as large as width*height*pixelSize. Its address should be a multiple
740
* of 4 if using RGBA mode.
742
* By default, image data is stored in the order of glDrawPixels: row-major
743
* order with the lower-left image pixel stored in the first array position
744
* (ie. bottom-to-top).
746
* If the context's viewport hasn't been initialized yet, it will now be
747
* initialized to (0,0,width,height).
749
* Input: osmesa - the rendering context
750
* buffer - the image buffer memory
751
* type - data type for pixel components
752
* GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT
754
* width, height - size of image buffer in pixels, at least 1
755
* Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
756
* invalid type, invalid size, etc.
758
GLAPI GLboolean GLAPIENTRY
759
OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
760
GLsizei width, GLsizei height)
762
struct st_api *stapi = get_st_api();
763
enum pipe_format color_format;
765
if (!osmesa && !buffer) {
766
stapi->make_current(stapi, NULL, NULL, NULL);
770
if (!osmesa || !buffer || width < 1 || height < 1) {
774
color_format = osmesa_choose_format(osmesa->format, type);
775
if (color_format == PIPE_FORMAT_NONE) {
776
fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n");
780
/* See if we already have a buffer that uses these pixel formats */
781
if (osmesa->current_buffer &&
782
(osmesa->current_buffer->visual.color_format != color_format ||
783
osmesa->current_buffer->visual.depth_stencil_format != osmesa->depth_stencil_format ||
784
osmesa->current_buffer->visual.accum_format != osmesa->accum_format ||
785
osmesa->current_buffer->width != width ||
786
osmesa->current_buffer->height != height)) {
787
osmesa_destroy_buffer(osmesa->current_buffer);
788
osmesa->current_buffer = NULL;
791
if (!osmesa->current_buffer) {
792
osmesa->current_buffer = osmesa_create_buffer(color_format,
793
osmesa->depth_stencil_format,
794
osmesa->accum_format);
797
struct osmesa_buffer *osbuffer = osmesa->current_buffer;
799
osbuffer->width = width;
800
osbuffer->height = height;
801
osbuffer->map = buffer;
805
stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb);
807
/* XXX: We should probably load the current color value into the buffer here
808
* to match classic swrast behavior (context's fb starts with the contents of
809
* your pixel buffer).
812
if (!osmesa->ever_used) {
813
/* one-time init, just postprocessing for now */
814
boolean any_pp_enabled = FALSE;
817
for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) {
818
if (osmesa->pp_enabled[i]) {
819
any_pp_enabled = TRUE;
824
if (any_pp_enabled) {
825
osmesa->pp = pp_init(osmesa->stctx->pipe,
827
osmesa->stctx->cso_context,
830
pp_init_fbos(osmesa->pp, width, height);
833
osmesa->ever_used = TRUE;
841
GLAPI OSMesaContext GLAPIENTRY
842
OSMesaGetCurrentContext(void)
844
struct st_api *stapi = get_st_api();
845
struct st_context_iface *st = stapi->get_current(stapi);
846
return st ? (OSMesaContext) st->st_manager_private : NULL;
851
GLAPI void GLAPIENTRY
852
OSMesaPixelStore(GLint pname, GLint value)
854
OSMesaContext osmesa = OSMesaGetCurrentContext();
857
case OSMESA_ROW_LENGTH:
858
osmesa->user_row_length = value;
861
osmesa->y_up = value ? GL_TRUE : GL_FALSE;
864
fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n");
870
GLAPI void GLAPIENTRY
871
OSMesaGetIntegerv(GLint pname, GLint *value)
873
OSMesaContext osmesa = OSMesaGetCurrentContext();
874
struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL;
878
*value = osbuffer ? osbuffer->width : 0;
881
*value = osbuffer ? osbuffer->height : 0;
884
*value = osmesa->format;
887
/* current color buffer's data type */
888
*value = osmesa->type;
890
case OSMESA_ROW_LENGTH:
891
*value = osmesa->user_row_length;
894
*value = osmesa->y_up;
896
case OSMESA_MAX_WIDTH:
898
case OSMESA_MAX_HEIGHT:
900
struct pipe_screen *screen = get_st_manager()->screen;
901
*value = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
905
fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n");
912
* Return information about the depth buffer associated with an OSMesa context.
913
* Input: c - the OSMesa context
914
* Output: width, height - size of buffer in pixels
915
* bytesPerValue - bytes per depth value (2 or 4)
916
* buffer - pointer to depth buffer values
917
* Return: GL_TRUE or GL_FALSE to indicate success or failure.
919
GLAPI GLboolean GLAPIENTRY
920
OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height,
921
GLint *bytesPerValue, void **buffer)
923
struct osmesa_buffer *osbuffer = c->current_buffer;
924
struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL];
934
*width = res->width0;
935
*height = res->height0;
936
*bytesPerValue = util_format_get_blocksize(res->format);
939
c->zs_stride = *width * *bytesPerValue;
940
c->zs = calloc(c->zs_stride, *height);
944
osmesa_read_buffer(c, res, c->zs, c->zs_stride, true);
954
* Return the color buffer associated with an OSMesa context.
955
* Input: c - the OSMesa context
956
* Output: width, height - size of buffer in pixels
957
* format - the pixel format (OSMESA_FORMAT)
958
* buffer - pointer to color buffer values
959
* Return: GL_TRUE or GL_FALSE to indicate success or failure.
961
GLAPI GLboolean GLAPIENTRY
962
OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width,
963
GLint *height, GLint *format, void **buffer)
965
struct osmesa_buffer *osbuffer = osmesa->current_buffer;
968
*width = osbuffer->width;
969
*height = osbuffer->height;
970
*format = osmesa->format;
971
*buffer = osbuffer->map;
990
static struct name_function functions[] = {
991
{ "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
992
{ "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
993
{ "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs },
994
{ "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
995
{ "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
996
{ "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
997
{ "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore },
998
{ "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
999
{ "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1000
{ "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1001
{ "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1002
{ "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1003
{ "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess },
1008
GLAPI OSMESAproc GLAPIENTRY
1009
OSMesaGetProcAddress(const char *funcName)
1012
for (i = 0; functions[i].Name; i++) {
1013
if (strcmp(functions[i].Name, funcName) == 0)
1014
return functions[i].Function;
1016
return _glapi_get_proc_address(funcName);
1020
GLAPI void GLAPIENTRY
1021
OSMesaColorClamp(GLboolean enable)
1023
extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp);
1025
_mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
1026
enable ? GL_TRUE : GL_FIXED_ONLY_ARB);
1030
GLAPI void GLAPIENTRY
1031
OSMesaPostprocess(OSMesaContext osmesa, const char *filter,
1032
unsigned enable_value)
1034
if (!osmesa->ever_used) {
1035
/* We can only enable/disable postprocess filters before a context
1036
* is made current for the first time.
1040
for (i = 0; i < PP_FILTERS; i++) {
1041
if (strcmp(pp_filters[i].name, filter) == 0) {
1042
osmesa->pp_enabled[i] = enable_value;
1046
debug_warning("OSMesaPostprocess(unknown filter)\n");
1049
debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n");