17ec681f3Smrg/* 27ec681f3Smrg * Copyright (c) 2013 Brian Paul All Rights Reserved. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice shall be included 127ec681f3Smrg * in all copies or substantial portions of the Software. 137ec681f3Smrg * 147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 157ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 187ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 197ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 207ec681f3Smrg * OTHER DEALINGS IN THE SOFTWARE. 217ec681f3Smrg */ 227ec681f3Smrg 237ec681f3Smrg 247ec681f3Smrg/* 257ec681f3Smrg * Off-Screen rendering into client memory. 267ec681f3Smrg * OpenGL gallium frontend for softpipe and llvmpipe. 277ec681f3Smrg * 287ec681f3Smrg * Notes: 297ec681f3Smrg * 307ec681f3Smrg * If Gallium is built with LLVM support we use the llvmpipe driver. 317ec681f3Smrg * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable 327ec681f3Smrg * may be set to "softpipe" or "llvmpipe" to override. 337ec681f3Smrg * 347ec681f3Smrg * With softpipe we could render directly into the user's buffer by using a 357ec681f3Smrg * display target resource. However, softpipe doesn't support "upside-down" 367ec681f3Smrg * rendering which would be needed for the OSMESA_Y_UP=TRUE case. 377ec681f3Smrg * 387ec681f3Smrg * With llvmpipe we could only render directly into the user's buffer when its 397ec681f3Smrg * width and height is a multiple of the tile size (64 pixels). 407ec681f3Smrg * 417ec681f3Smrg * Because of these constraints we always render into ordinary resources then 427ec681f3Smrg * copy the results to the user's buffer in the flush_front() function which 437ec681f3Smrg * is called when the app calls glFlush/Finish. 447ec681f3Smrg * 457ec681f3Smrg * In general, the OSMesa interface is pretty ugly and not a good match 467ec681f3Smrg * for Gallium. But we're interested in doing the best we can to preserve 477ec681f3Smrg * application portability. With a little work we could come up with a 487ec681f3Smrg * much nicer, new off-screen Gallium interface... 497ec681f3Smrg */ 507ec681f3Smrg 517ec681f3Smrg 527ec681f3Smrg#include <stdio.h> 537ec681f3Smrg#include <c11/threads.h> 547ec681f3Smrg#include "GL/osmesa.h" 557ec681f3Smrg 567ec681f3Smrg#include "glapi/glapi.h" /* for OSMesaGetProcAddress below */ 577ec681f3Smrg 587ec681f3Smrg#include "pipe/p_context.h" 597ec681f3Smrg#include "pipe/p_screen.h" 607ec681f3Smrg#include "pipe/p_state.h" 617ec681f3Smrg 627ec681f3Smrg#include "util/u_atomic.h" 637ec681f3Smrg#include "util/u_box.h" 647ec681f3Smrg#include "util/u_debug.h" 657ec681f3Smrg#include "util/format/u_format.h" 667ec681f3Smrg#include "util/u_inlines.h" 677ec681f3Smrg#include "util/u_memory.h" 687ec681f3Smrg 697ec681f3Smrg#include "postprocess/filters.h" 707ec681f3Smrg#include "postprocess/postprocess.h" 717ec681f3Smrg 727ec681f3Smrg#include "frontend/api.h" 737ec681f3Smrg#include "state_tracker/st_gl_api.h" 747ec681f3Smrg 757ec681f3Smrg 767ec681f3Smrg 777ec681f3Smrgextern struct pipe_screen * 787ec681f3Smrgosmesa_create_screen(void); 797ec681f3Smrg 807ec681f3Smrg 817ec681f3Smrg 827ec681f3Smrgstruct osmesa_buffer 837ec681f3Smrg{ 847ec681f3Smrg struct st_framebuffer_iface *stfb; 857ec681f3Smrg struct st_visual visual; 867ec681f3Smrg unsigned width, height; 877ec681f3Smrg 887ec681f3Smrg struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 897ec681f3Smrg 907ec681f3Smrg void *map; 917ec681f3Smrg 927ec681f3Smrg struct osmesa_buffer *next; /**< next in linked list */ 937ec681f3Smrg}; 947ec681f3Smrg 957ec681f3Smrg 967ec681f3Smrgstruct osmesa_context 977ec681f3Smrg{ 987ec681f3Smrg struct st_context_iface *stctx; 997ec681f3Smrg 1007ec681f3Smrg boolean ever_used; /*< Has this context ever been current? */ 1017ec681f3Smrg 1027ec681f3Smrg struct osmesa_buffer *current_buffer; 1037ec681f3Smrg 1047ec681f3Smrg /* Storage for depth/stencil, if the user has requested access. The backing 1057ec681f3Smrg * driver always has its own storage for the actual depth/stencil, which we 1067ec681f3Smrg * have to transfer in and out. 1077ec681f3Smrg */ 1087ec681f3Smrg void *zs; 1097ec681f3Smrg unsigned zs_stride; 1107ec681f3Smrg 1117ec681f3Smrg enum pipe_format depth_stencil_format, accum_format; 1127ec681f3Smrg 1137ec681f3Smrg GLenum format; /*< User-specified context format */ 1147ec681f3Smrg GLenum type; /*< Buffer's data type */ 1157ec681f3Smrg GLint user_row_length; /*< user-specified number of pixels per row */ 1167ec681f3Smrg GLboolean y_up; /*< TRUE -> Y increases upward */ 1177ec681f3Smrg /*< FALSE -> Y increases downward */ 1187ec681f3Smrg 1197ec681f3Smrg /** Which postprocessing filters are enabled. */ 1207ec681f3Smrg unsigned pp_enabled[PP_FILTERS]; 1217ec681f3Smrg struct pp_queue_t *pp; 1227ec681f3Smrg}; 1237ec681f3Smrg 1247ec681f3Smrg/** 1257ec681f3Smrg * Called from the ST manager. 1267ec681f3Smrg */ 1277ec681f3Smrgstatic int 1287ec681f3Smrgosmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param) 1297ec681f3Smrg{ 1307ec681f3Smrg /* no-op */ 1317ec681f3Smrg return 0; 1327ec681f3Smrg} 1337ec681f3Smrg 1347ec681f3Smrgstatic struct st_manager *stmgr = NULL; 1357ec681f3Smrgstatic struct st_api *stapi = NULL; 1367ec681f3Smrg 1377ec681f3Smrgstatic void 1387ec681f3Smrgdestroy_st_manager(void) 1397ec681f3Smrg{ 1407ec681f3Smrg if (stmgr) { 1417ec681f3Smrg if (stmgr->screen) 1427ec681f3Smrg stmgr->screen->destroy(stmgr->screen); 1437ec681f3Smrg FREE(stmgr); 1447ec681f3Smrg } 1457ec681f3Smrg 1467ec681f3Smrg if (stapi && stapi->destroy) { 1477ec681f3Smrg stapi->destroy(stapi); 1487ec681f3Smrg } 1497ec681f3Smrg} 1507ec681f3Smrg 1517ec681f3Smrgstatic void 1527ec681f3Smrgcreate_st_manager(void) 1537ec681f3Smrg{ 1547ec681f3Smrg if (atexit(destroy_st_manager) != 0) 1557ec681f3Smrg return; 1567ec681f3Smrg 1577ec681f3Smrg stmgr = CALLOC_STRUCT(st_manager); 1587ec681f3Smrg if (stmgr) { 1597ec681f3Smrg stmgr->screen = osmesa_create_screen(); 1607ec681f3Smrg stmgr->get_param = osmesa_st_get_param; 1617ec681f3Smrg stmgr->get_egl_image = NULL; 1627ec681f3Smrg } 1637ec681f3Smrg 1647ec681f3Smrg stapi = st_gl_api_create(); 1657ec681f3Smrg} 1667ec681f3Smrg 1677ec681f3Smrg/** 1687ec681f3Smrg * Create/return a singleton st_manager object. 1697ec681f3Smrg */ 1707ec681f3Smrgstatic struct st_manager * 1717ec681f3Smrgget_st_manager(void) 1727ec681f3Smrg{ 1737ec681f3Smrg static once_flag create_once_flag = ONCE_FLAG_INIT; 1747ec681f3Smrg 1757ec681f3Smrg call_once(&create_once_flag, create_st_manager); 1767ec681f3Smrg 1777ec681f3Smrg return stmgr; 1787ec681f3Smrg} 1797ec681f3Smrg 1807ec681f3Smrg/** 1817ec681f3Smrg * Create/return singleton st_api object. 1827ec681f3Smrg */ 1837ec681f3Smrgstatic struct st_api * 1847ec681f3Smrgget_st_api(void) 1857ec681f3Smrg{ 1867ec681f3Smrg get_st_manager(); 1877ec681f3Smrg return stapi; 1887ec681f3Smrg} 1897ec681f3Smrg 1907ec681f3Smrg/* Reads the color or depth buffer from the backing context to either the user storage 1917ec681f3Smrg * (color buffer) or our temporary (z/s) 1927ec681f3Smrg */ 1937ec681f3Smrgstatic void 1947ec681f3Smrgosmesa_read_buffer(OSMesaContext osmesa, struct pipe_resource *res, void *dst, 1957ec681f3Smrg int dst_stride, bool y_up) 1967ec681f3Smrg{ 1977ec681f3Smrg struct pipe_context *pipe = osmesa->stctx->pipe; 1987ec681f3Smrg 1997ec681f3Smrg struct pipe_box box; 2007ec681f3Smrg u_box_2d(0, 0, res->width0, res->height0, &box); 2017ec681f3Smrg 2027ec681f3Smrg struct pipe_transfer *transfer = NULL; 2037ec681f3Smrg ubyte *src = pipe->texture_map(pipe, res, 0, PIPE_MAP_READ, &box, 2047ec681f3Smrg &transfer); 2057ec681f3Smrg 2067ec681f3Smrg /* 2077ec681f3Smrg * Copy the color buffer from the resource to the user's buffer. 2087ec681f3Smrg */ 2097ec681f3Smrg 2107ec681f3Smrg if (y_up) { 2117ec681f3Smrg /* need to flip image upside down */ 2127ec681f3Smrg dst = (ubyte *)dst + (res->height0 - 1) * dst_stride; 2137ec681f3Smrg dst_stride = -dst_stride; 2147ec681f3Smrg } 2157ec681f3Smrg 2167ec681f3Smrg unsigned bpp = util_format_get_blocksize(res->format); 2177ec681f3Smrg for (unsigned y = 0; y < res->height0; y++) 2187ec681f3Smrg { 2197ec681f3Smrg memcpy(dst, src, bpp * res->width0); 2207ec681f3Smrg dst = (ubyte *)dst + dst_stride; 2217ec681f3Smrg src += transfer->stride; 2227ec681f3Smrg } 2237ec681f3Smrg 2247ec681f3Smrg pipe->texture_unmap(pipe, transfer); 2257ec681f3Smrg} 2267ec681f3Smrg 2277ec681f3Smrg 2287ec681f3Smrg/** 2297ec681f3Smrg * Given an OSMESA_x format and a GL_y type, return the best 2307ec681f3Smrg * matching PIPE_FORMAT_z. 2317ec681f3Smrg * Note that we can't exactly match all user format/type combinations 2327ec681f3Smrg * with gallium formats. If we find this to be a problem, we can 2337ec681f3Smrg * implement more elaborate format/type conversion in the flush_front() 2347ec681f3Smrg * function. 2357ec681f3Smrg */ 2367ec681f3Smrgstatic enum pipe_format 2377ec681f3Smrgosmesa_choose_format(GLenum format, GLenum type) 2387ec681f3Smrg{ 2397ec681f3Smrg switch (format) { 2407ec681f3Smrg case OSMESA_RGBA: 2417ec681f3Smrg if (type == GL_UNSIGNED_BYTE) { 2427ec681f3Smrg#if UTIL_ARCH_LITTLE_ENDIAN 2437ec681f3Smrg return PIPE_FORMAT_R8G8B8A8_UNORM; 2447ec681f3Smrg#else 2457ec681f3Smrg return PIPE_FORMAT_A8B8G8R8_UNORM; 2467ec681f3Smrg#endif 2477ec681f3Smrg } 2487ec681f3Smrg else if (type == GL_UNSIGNED_SHORT) { 2497ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 2507ec681f3Smrg } 2517ec681f3Smrg else if (type == GL_FLOAT) { 2527ec681f3Smrg return PIPE_FORMAT_R32G32B32A32_FLOAT; 2537ec681f3Smrg } 2547ec681f3Smrg else { 2557ec681f3Smrg return PIPE_FORMAT_NONE; 2567ec681f3Smrg } 2577ec681f3Smrg break; 2587ec681f3Smrg case OSMESA_BGRA: 2597ec681f3Smrg if (type == GL_UNSIGNED_BYTE) { 2607ec681f3Smrg#if UTIL_ARCH_LITTLE_ENDIAN 2617ec681f3Smrg return PIPE_FORMAT_B8G8R8A8_UNORM; 2627ec681f3Smrg#else 2637ec681f3Smrg return PIPE_FORMAT_A8R8G8B8_UNORM; 2647ec681f3Smrg#endif 2657ec681f3Smrg } 2667ec681f3Smrg else if (type == GL_UNSIGNED_SHORT) { 2677ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 2687ec681f3Smrg } 2697ec681f3Smrg else if (type == GL_FLOAT) { 2707ec681f3Smrg return PIPE_FORMAT_R32G32B32A32_FLOAT; 2717ec681f3Smrg } 2727ec681f3Smrg else { 2737ec681f3Smrg return PIPE_FORMAT_NONE; 2747ec681f3Smrg } 2757ec681f3Smrg break; 2767ec681f3Smrg case OSMESA_ARGB: 2777ec681f3Smrg if (type == GL_UNSIGNED_BYTE) { 2787ec681f3Smrg#if UTIL_ARCH_LITTLE_ENDIAN 2797ec681f3Smrg return PIPE_FORMAT_A8R8G8B8_UNORM; 2807ec681f3Smrg#else 2817ec681f3Smrg return PIPE_FORMAT_B8G8R8A8_UNORM; 2827ec681f3Smrg#endif 2837ec681f3Smrg } 2847ec681f3Smrg else if (type == GL_UNSIGNED_SHORT) { 2857ec681f3Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 2867ec681f3Smrg } 2877ec681f3Smrg else if (type == GL_FLOAT) { 2887ec681f3Smrg return PIPE_FORMAT_R32G32B32A32_FLOAT; 2897ec681f3Smrg } 2907ec681f3Smrg else { 2917ec681f3Smrg return PIPE_FORMAT_NONE; 2927ec681f3Smrg } 2937ec681f3Smrg break; 2947ec681f3Smrg case OSMESA_RGB: 2957ec681f3Smrg if (type == GL_UNSIGNED_BYTE) { 2967ec681f3Smrg return PIPE_FORMAT_R8G8B8_UNORM; 2977ec681f3Smrg } 2987ec681f3Smrg else if (type == GL_UNSIGNED_SHORT) { 2997ec681f3Smrg return PIPE_FORMAT_R16G16B16_UNORM; 3007ec681f3Smrg } 3017ec681f3Smrg else if (type == GL_FLOAT) { 3027ec681f3Smrg return PIPE_FORMAT_R32G32B32_FLOAT; 3037ec681f3Smrg } 3047ec681f3Smrg else { 3057ec681f3Smrg return PIPE_FORMAT_NONE; 3067ec681f3Smrg } 3077ec681f3Smrg break; 3087ec681f3Smrg case OSMESA_BGR: 3097ec681f3Smrg /* No gallium format for this one */ 3107ec681f3Smrg return PIPE_FORMAT_NONE; 3117ec681f3Smrg case OSMESA_RGB_565: 3127ec681f3Smrg if (type != GL_UNSIGNED_SHORT_5_6_5) 3137ec681f3Smrg return PIPE_FORMAT_NONE; 3147ec681f3Smrg return PIPE_FORMAT_B5G6R5_UNORM; 3157ec681f3Smrg default: 3167ec681f3Smrg return PIPE_FORMAT_NONE; 3177ec681f3Smrg } 3187ec681f3Smrg} 3197ec681f3Smrg 3207ec681f3Smrg 3217ec681f3Smrg/** 3227ec681f3Smrg * Initialize an st_visual object. 3237ec681f3Smrg */ 3247ec681f3Smrgstatic void 3257ec681f3Smrgosmesa_init_st_visual(struct st_visual *vis, 3267ec681f3Smrg enum pipe_format color_format, 3277ec681f3Smrg enum pipe_format ds_format, 3287ec681f3Smrg enum pipe_format accum_format) 3297ec681f3Smrg{ 3307ec681f3Smrg vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; 3317ec681f3Smrg 3327ec681f3Smrg if (ds_format != PIPE_FORMAT_NONE) 3337ec681f3Smrg vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 3347ec681f3Smrg if (accum_format != PIPE_FORMAT_NONE) 3357ec681f3Smrg vis->buffer_mask |= ST_ATTACHMENT_ACCUM; 3367ec681f3Smrg 3377ec681f3Smrg vis->color_format = color_format; 3387ec681f3Smrg vis->depth_stencil_format = ds_format; 3397ec681f3Smrg vis->accum_format = accum_format; 3407ec681f3Smrg vis->samples = 1; 3417ec681f3Smrg} 3427ec681f3Smrg 3437ec681f3Smrg 3447ec681f3Smrg/** 3457ec681f3Smrg * Return the osmesa_buffer that corresponds to an st_framebuffer_iface. 3467ec681f3Smrg */ 3477ec681f3Smrgstatic inline struct osmesa_buffer * 3487ec681f3Smrgstfbi_to_osbuffer(struct st_framebuffer_iface *stfbi) 3497ec681f3Smrg{ 3507ec681f3Smrg return (struct osmesa_buffer *) stfbi->st_manager_private; 3517ec681f3Smrg} 3527ec681f3Smrg 3537ec681f3Smrg 3547ec681f3Smrg/** 3557ec681f3Smrg * Called via glFlush/glFinish. This is where we copy the contents 3567ec681f3Smrg * of the driver's color buffer into the user-specified buffer. 3577ec681f3Smrg */ 3587ec681f3Smrgstatic bool 3597ec681f3Smrgosmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, 3607ec681f3Smrg struct st_framebuffer_iface *stfbi, 3617ec681f3Smrg enum st_attachment_type statt) 3627ec681f3Smrg{ 3637ec681f3Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 3647ec681f3Smrg struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); 3657ec681f3Smrg struct pipe_resource *res = osbuffer->textures[statt]; 3667ec681f3Smrg unsigned bpp; 3677ec681f3Smrg int dst_stride; 3687ec681f3Smrg 3697ec681f3Smrg if (statt != ST_ATTACHMENT_FRONT_LEFT) 3707ec681f3Smrg return false; 3717ec681f3Smrg 3727ec681f3Smrg if (osmesa->pp) { 3737ec681f3Smrg struct pipe_resource *zsbuf = NULL; 3747ec681f3Smrg unsigned i; 3757ec681f3Smrg 3767ec681f3Smrg /* Find the z/stencil buffer if there is one */ 3777ec681f3Smrg for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) { 3787ec681f3Smrg struct pipe_resource *res = osbuffer->textures[i]; 3797ec681f3Smrg if (res) { 3807ec681f3Smrg const struct util_format_description *desc = 3817ec681f3Smrg util_format_description(res->format); 3827ec681f3Smrg 3837ec681f3Smrg if (util_format_has_depth(desc)) { 3847ec681f3Smrg zsbuf = res; 3857ec681f3Smrg break; 3867ec681f3Smrg } 3877ec681f3Smrg } 3887ec681f3Smrg } 3897ec681f3Smrg 3907ec681f3Smrg /* run the postprocess stage(s) */ 3917ec681f3Smrg pp_run(osmesa->pp, res, res, zsbuf); 3927ec681f3Smrg } 3937ec681f3Smrg 3947ec681f3Smrg /* Snapshot the color buffer to the user's buffer. */ 3957ec681f3Smrg bpp = util_format_get_blocksize(osbuffer->visual.color_format); 3967ec681f3Smrg if (osmesa->user_row_length) 3977ec681f3Smrg dst_stride = bpp * osmesa->user_row_length; 3987ec681f3Smrg else 3997ec681f3Smrg dst_stride = bpp * osbuffer->width; 4007ec681f3Smrg 4017ec681f3Smrg osmesa_read_buffer(osmesa, res, osbuffer->map, dst_stride, osmesa->y_up); 4027ec681f3Smrg 4037ec681f3Smrg /* If the user has requested the Z/S buffer, then snapshot that one too. */ 4047ec681f3Smrg if (osmesa->zs) { 4057ec681f3Smrg osmesa_read_buffer(osmesa, osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL], 4067ec681f3Smrg osmesa->zs, osmesa->zs_stride, true); 4077ec681f3Smrg } 4087ec681f3Smrg 4097ec681f3Smrg return true; 4107ec681f3Smrg} 4117ec681f3Smrg 4127ec681f3Smrg 4137ec681f3Smrg/** 4147ec681f3Smrg * Called by the st manager to validate the framebuffer (allocate 4157ec681f3Smrg * its resources). 4167ec681f3Smrg */ 4177ec681f3Smrgstatic bool 4187ec681f3Smrgosmesa_st_framebuffer_validate(struct st_context_iface *stctx, 4197ec681f3Smrg struct st_framebuffer_iface *stfbi, 4207ec681f3Smrg const enum st_attachment_type *statts, 4217ec681f3Smrg unsigned count, 4227ec681f3Smrg struct pipe_resource **out) 4237ec681f3Smrg{ 4247ec681f3Smrg struct pipe_screen *screen = get_st_manager()->screen; 4257ec681f3Smrg enum st_attachment_type i; 4267ec681f3Smrg struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); 4277ec681f3Smrg struct pipe_resource templat; 4287ec681f3Smrg 4297ec681f3Smrg memset(&templat, 0, sizeof(templat)); 4307ec681f3Smrg templat.target = PIPE_TEXTURE_RECT; 4317ec681f3Smrg templat.format = 0; /* setup below */ 4327ec681f3Smrg templat.last_level = 0; 4337ec681f3Smrg templat.width0 = osbuffer->width; 4347ec681f3Smrg templat.height0 = osbuffer->height; 4357ec681f3Smrg templat.depth0 = 1; 4367ec681f3Smrg templat.array_size = 1; 4377ec681f3Smrg templat.usage = PIPE_USAGE_DEFAULT; 4387ec681f3Smrg templat.bind = 0; /* setup below */ 4397ec681f3Smrg templat.flags = 0; 4407ec681f3Smrg 4417ec681f3Smrg for (i = 0; i < count; i++) { 4427ec681f3Smrg enum pipe_format format = PIPE_FORMAT_NONE; 4437ec681f3Smrg unsigned bind = 0; 4447ec681f3Smrg 4457ec681f3Smrg /* 4467ec681f3Smrg * At this time, we really only need to handle the front-left color 4477ec681f3Smrg * attachment, since that's all we specified for the visual in 4487ec681f3Smrg * osmesa_init_st_visual(). 4497ec681f3Smrg */ 4507ec681f3Smrg if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) { 4517ec681f3Smrg format = osbuffer->visual.color_format; 4527ec681f3Smrg bind = PIPE_BIND_RENDER_TARGET; 4537ec681f3Smrg } 4547ec681f3Smrg else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 4557ec681f3Smrg format = osbuffer->visual.depth_stencil_format; 4567ec681f3Smrg bind = PIPE_BIND_DEPTH_STENCIL; 4577ec681f3Smrg } 4587ec681f3Smrg else if (statts[i] == ST_ATTACHMENT_ACCUM) { 4597ec681f3Smrg format = osbuffer->visual.accum_format; 4607ec681f3Smrg bind = PIPE_BIND_RENDER_TARGET; 4617ec681f3Smrg } 4627ec681f3Smrg else { 4637ec681f3Smrg debug_warning("Unexpected attachment type in " 4647ec681f3Smrg "osmesa_st_framebuffer_validate()"); 4657ec681f3Smrg } 4667ec681f3Smrg 4677ec681f3Smrg templat.format = format; 4687ec681f3Smrg templat.bind = bind; 4697ec681f3Smrg pipe_resource_reference(&out[i], NULL); 4707ec681f3Smrg out[i] = osbuffer->textures[statts[i]] = 4717ec681f3Smrg screen->resource_create(screen, &templat); 4727ec681f3Smrg } 4737ec681f3Smrg 4747ec681f3Smrg return true; 4757ec681f3Smrg} 4767ec681f3Smrg 4777ec681f3Smrgstatic uint32_t osmesa_fb_ID = 0; 4787ec681f3Smrg 4797ec681f3Smrgstatic struct st_framebuffer_iface * 4807ec681f3Smrgosmesa_create_st_framebuffer(void) 4817ec681f3Smrg{ 4827ec681f3Smrg struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface); 4837ec681f3Smrg if (stfbi) { 4847ec681f3Smrg stfbi->flush_front = osmesa_st_framebuffer_flush_front; 4857ec681f3Smrg stfbi->validate = osmesa_st_framebuffer_validate; 4867ec681f3Smrg p_atomic_set(&stfbi->stamp, 1); 4877ec681f3Smrg stfbi->ID = p_atomic_inc_return(&osmesa_fb_ID); 4887ec681f3Smrg stfbi->state_manager = get_st_manager(); 4897ec681f3Smrg } 4907ec681f3Smrg return stfbi; 4917ec681f3Smrg} 4927ec681f3Smrg 4937ec681f3Smrg 4947ec681f3Smrg/** 4957ec681f3Smrg * Create new buffer and add to linked list. 4967ec681f3Smrg */ 4977ec681f3Smrgstatic struct osmesa_buffer * 4987ec681f3Smrgosmesa_create_buffer(enum pipe_format color_format, 4997ec681f3Smrg enum pipe_format ds_format, 5007ec681f3Smrg enum pipe_format accum_format) 5017ec681f3Smrg{ 5027ec681f3Smrg struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer); 5037ec681f3Smrg if (osbuffer) { 5047ec681f3Smrg osbuffer->stfb = osmesa_create_st_framebuffer(); 5057ec681f3Smrg 5067ec681f3Smrg osbuffer->stfb->st_manager_private = osbuffer; 5077ec681f3Smrg osbuffer->stfb->visual = &osbuffer->visual; 5087ec681f3Smrg 5097ec681f3Smrg osmesa_init_st_visual(&osbuffer->visual, color_format, 5107ec681f3Smrg ds_format, accum_format); 5117ec681f3Smrg } 5127ec681f3Smrg 5137ec681f3Smrg return osbuffer; 5147ec681f3Smrg} 5157ec681f3Smrg 5167ec681f3Smrg 5177ec681f3Smrgstatic void 5187ec681f3Smrgosmesa_destroy_buffer(struct osmesa_buffer *osbuffer) 5197ec681f3Smrg{ 5207ec681f3Smrg /* 5217ec681f3Smrg * Notify the state manager that the associated framebuffer interface 5227ec681f3Smrg * is no longer valid. 5237ec681f3Smrg */ 5247ec681f3Smrg stapi->destroy_drawable(stapi, osbuffer->stfb); 5257ec681f3Smrg 5267ec681f3Smrg FREE(osbuffer->stfb); 5277ec681f3Smrg FREE(osbuffer); 5287ec681f3Smrg} 5297ec681f3Smrg 5307ec681f3Smrg 5317ec681f3Smrg 5327ec681f3Smrg/**********************************************************************/ 5337ec681f3Smrg/***** Public Functions *****/ 5347ec681f3Smrg/**********************************************************************/ 5357ec681f3Smrg 5367ec681f3Smrg 5377ec681f3Smrg/** 5387ec681f3Smrg * Create an Off-Screen Mesa rendering context. The only attribute needed is 5397ec681f3Smrg * an RGBA vs Color-Index mode flag. 5407ec681f3Smrg * 5417ec681f3Smrg * Input: format - Must be GL_RGBA 5427ec681f3Smrg * sharelist - specifies another OSMesaContext with which to share 5437ec681f3Smrg * display lists. NULL indicates no sharing. 5447ec681f3Smrg * Return: an OSMesaContext or 0 if error 5457ec681f3Smrg */ 5467ec681f3SmrgGLAPI OSMesaContext GLAPIENTRY 5477ec681f3SmrgOSMesaCreateContext(GLenum format, OSMesaContext sharelist) 5487ec681f3Smrg{ 5497ec681f3Smrg return OSMesaCreateContextExt(format, 24, 8, 0, sharelist); 5507ec681f3Smrg} 5517ec681f3Smrg 5527ec681f3Smrg 5537ec681f3Smrg/** 5547ec681f3Smrg * New in Mesa 3.5 5557ec681f3Smrg * 5567ec681f3Smrg * Create context and specify size of ancillary buffers. 5577ec681f3Smrg */ 5587ec681f3SmrgGLAPI OSMesaContext GLAPIENTRY 5597ec681f3SmrgOSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits, 5607ec681f3Smrg GLint accumBits, OSMesaContext sharelist) 5617ec681f3Smrg{ 5627ec681f3Smrg int attribs[100], n = 0; 5637ec681f3Smrg 5647ec681f3Smrg attribs[n++] = OSMESA_FORMAT; 5657ec681f3Smrg attribs[n++] = format; 5667ec681f3Smrg attribs[n++] = OSMESA_DEPTH_BITS; 5677ec681f3Smrg attribs[n++] = depthBits; 5687ec681f3Smrg attribs[n++] = OSMESA_STENCIL_BITS; 5697ec681f3Smrg attribs[n++] = stencilBits; 5707ec681f3Smrg attribs[n++] = OSMESA_ACCUM_BITS; 5717ec681f3Smrg attribs[n++] = accumBits; 5727ec681f3Smrg attribs[n++] = 0; 5737ec681f3Smrg 5747ec681f3Smrg return OSMesaCreateContextAttribs(attribs, sharelist); 5757ec681f3Smrg} 5767ec681f3Smrg 5777ec681f3Smrg 5787ec681f3Smrg/** 5797ec681f3Smrg * New in Mesa 11.2 5807ec681f3Smrg * 5817ec681f3Smrg * Create context with attribute list. 5827ec681f3Smrg */ 5837ec681f3SmrgGLAPI OSMesaContext GLAPIENTRY 5847ec681f3SmrgOSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist) 5857ec681f3Smrg{ 5867ec681f3Smrg OSMesaContext osmesa; 5877ec681f3Smrg struct st_context_iface *st_shared; 5887ec681f3Smrg enum st_context_error st_error = 0; 5897ec681f3Smrg struct st_context_attribs attribs; 5907ec681f3Smrg struct st_api *stapi = get_st_api(); 5917ec681f3Smrg GLenum format = GL_RGBA; 5927ec681f3Smrg int depthBits = 0, stencilBits = 0, accumBits = 0; 5937ec681f3Smrg int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0; 5947ec681f3Smrg int i; 5957ec681f3Smrg 5967ec681f3Smrg if (sharelist) { 5977ec681f3Smrg st_shared = sharelist->stctx; 5987ec681f3Smrg } 5997ec681f3Smrg else { 6007ec681f3Smrg st_shared = NULL; 6017ec681f3Smrg } 6027ec681f3Smrg 6037ec681f3Smrg for (i = 0; attribList[i]; i += 2) { 6047ec681f3Smrg switch (attribList[i]) { 6057ec681f3Smrg case OSMESA_FORMAT: 6067ec681f3Smrg format = attribList[i+1]; 6077ec681f3Smrg switch (format) { 6087ec681f3Smrg case OSMESA_COLOR_INDEX: 6097ec681f3Smrg case OSMESA_RGBA: 6107ec681f3Smrg case OSMESA_BGRA: 6117ec681f3Smrg case OSMESA_ARGB: 6127ec681f3Smrg case OSMESA_RGB: 6137ec681f3Smrg case OSMESA_BGR: 6147ec681f3Smrg case OSMESA_RGB_565: 6157ec681f3Smrg /* legal */ 6167ec681f3Smrg break; 6177ec681f3Smrg default: 6187ec681f3Smrg return NULL; 6197ec681f3Smrg } 6207ec681f3Smrg break; 6217ec681f3Smrg case OSMESA_DEPTH_BITS: 6227ec681f3Smrg depthBits = attribList[i+1]; 6237ec681f3Smrg if (depthBits < 0) 6247ec681f3Smrg return NULL; 6257ec681f3Smrg break; 6267ec681f3Smrg case OSMESA_STENCIL_BITS: 6277ec681f3Smrg stencilBits = attribList[i+1]; 6287ec681f3Smrg if (stencilBits < 0) 6297ec681f3Smrg return NULL; 6307ec681f3Smrg break; 6317ec681f3Smrg case OSMESA_ACCUM_BITS: 6327ec681f3Smrg accumBits = attribList[i+1]; 6337ec681f3Smrg if (accumBits < 0) 6347ec681f3Smrg return NULL; 6357ec681f3Smrg break; 6367ec681f3Smrg case OSMESA_PROFILE: 6377ec681f3Smrg profile = attribList[i+1]; 6387ec681f3Smrg if (profile != OSMESA_CORE_PROFILE && 6397ec681f3Smrg profile != OSMESA_COMPAT_PROFILE) 6407ec681f3Smrg return NULL; 6417ec681f3Smrg break; 6427ec681f3Smrg case OSMESA_CONTEXT_MAJOR_VERSION: 6437ec681f3Smrg version_major = attribList[i+1]; 6447ec681f3Smrg if (version_major < 1) 6457ec681f3Smrg return NULL; 6467ec681f3Smrg break; 6477ec681f3Smrg case OSMESA_CONTEXT_MINOR_VERSION: 6487ec681f3Smrg version_minor = attribList[i+1]; 6497ec681f3Smrg if (version_minor < 0) 6507ec681f3Smrg return NULL; 6517ec681f3Smrg break; 6527ec681f3Smrg case 0: 6537ec681f3Smrg /* end of list */ 6547ec681f3Smrg break; 6557ec681f3Smrg default: 6567ec681f3Smrg fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n"); 6577ec681f3Smrg return NULL; 6587ec681f3Smrg } 6597ec681f3Smrg } 6607ec681f3Smrg 6617ec681f3Smrg osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 6627ec681f3Smrg if (!osmesa) 6637ec681f3Smrg return NULL; 6647ec681f3Smrg 6657ec681f3Smrg /* Choose depth/stencil/accum buffer formats */ 6667ec681f3Smrg if (accumBits > 0) { 6677ec681f3Smrg osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM; 6687ec681f3Smrg } 6697ec681f3Smrg if (depthBits > 0 && stencilBits > 0) { 6707ec681f3Smrg osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT; 6717ec681f3Smrg } 6727ec681f3Smrg else if (stencilBits > 0) { 6737ec681f3Smrg osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT; 6747ec681f3Smrg } 6757ec681f3Smrg else if (depthBits >= 24) { 6767ec681f3Smrg osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM; 6777ec681f3Smrg } 6787ec681f3Smrg else if (depthBits >= 16) { 6797ec681f3Smrg osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; 6807ec681f3Smrg } 6817ec681f3Smrg 6827ec681f3Smrg /* 6837ec681f3Smrg * Create the rendering context 6847ec681f3Smrg */ 6857ec681f3Smrg memset(&attribs, 0, sizeof(attribs)); 6867ec681f3Smrg attribs.profile = (profile == OSMESA_CORE_PROFILE) 6877ec681f3Smrg ? ST_PROFILE_OPENGL_CORE : ST_PROFILE_DEFAULT; 6887ec681f3Smrg attribs.major = version_major; 6897ec681f3Smrg attribs.minor = version_minor; 6907ec681f3Smrg attribs.flags = 0; /* ST_CONTEXT_FLAG_x */ 6917ec681f3Smrg attribs.options.force_glsl_extensions_warn = FALSE; 6927ec681f3Smrg attribs.options.disable_blend_func_extended = FALSE; 6937ec681f3Smrg attribs.options.disable_glsl_line_continuations = FALSE; 6947ec681f3Smrg attribs.options.force_glsl_version = 0; 6957ec681f3Smrg 6967ec681f3Smrg osmesa_init_st_visual(&attribs.visual, 6977ec681f3Smrg PIPE_FORMAT_NONE, 6987ec681f3Smrg osmesa->depth_stencil_format, 6997ec681f3Smrg osmesa->accum_format); 7007ec681f3Smrg 7017ec681f3Smrg osmesa->stctx = stapi->create_context(stapi, get_st_manager(), 7027ec681f3Smrg &attribs, &st_error, st_shared); 7037ec681f3Smrg if (!osmesa->stctx) { 7047ec681f3Smrg FREE(osmesa); 7057ec681f3Smrg return NULL; 7067ec681f3Smrg } 7077ec681f3Smrg 7087ec681f3Smrg osmesa->stctx->st_manager_private = osmesa; 7097ec681f3Smrg 7107ec681f3Smrg osmesa->format = format; 7117ec681f3Smrg osmesa->user_row_length = 0; 7127ec681f3Smrg osmesa->y_up = GL_TRUE; 7137ec681f3Smrg 7147ec681f3Smrg return osmesa; 7157ec681f3Smrg} 7167ec681f3Smrg 7177ec681f3Smrg 7187ec681f3Smrg 7197ec681f3Smrg/** 7207ec681f3Smrg * Destroy an Off-Screen Mesa rendering context. 7217ec681f3Smrg * 7227ec681f3Smrg * \param osmesa the context to destroy 7237ec681f3Smrg */ 7247ec681f3SmrgGLAPI void GLAPIENTRY 7257ec681f3SmrgOSMesaDestroyContext(OSMesaContext osmesa) 7267ec681f3Smrg{ 7277ec681f3Smrg if (osmesa) { 7287ec681f3Smrg pp_free(osmesa->pp); 7297ec681f3Smrg osmesa->stctx->destroy(osmesa->stctx); 7307ec681f3Smrg free(osmesa->zs); 7317ec681f3Smrg FREE(osmesa); 7327ec681f3Smrg } 7337ec681f3Smrg} 7347ec681f3Smrg 7357ec681f3Smrg 7367ec681f3Smrg/** 7377ec681f3Smrg * Bind an OSMesaContext to an image buffer. The image buffer is just a 7387ec681f3Smrg * block of memory which the client provides. Its size must be at least 7397ec681f3Smrg * as large as width*height*pixelSize. Its address should be a multiple 7407ec681f3Smrg * of 4 if using RGBA mode. 7417ec681f3Smrg * 7427ec681f3Smrg * By default, image data is stored in the order of glDrawPixels: row-major 7437ec681f3Smrg * order with the lower-left image pixel stored in the first array position 7447ec681f3Smrg * (ie. bottom-to-top). 7457ec681f3Smrg * 7467ec681f3Smrg * If the context's viewport hasn't been initialized yet, it will now be 7477ec681f3Smrg * initialized to (0,0,width,height). 7487ec681f3Smrg * 7497ec681f3Smrg * Input: osmesa - the rendering context 7507ec681f3Smrg * buffer - the image buffer memory 7517ec681f3Smrg * type - data type for pixel components 7527ec681f3Smrg * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT 7537ec681f3Smrg * or GL_FLOAT. 7547ec681f3Smrg * width, height - size of image buffer in pixels, at least 1 7557ec681f3Smrg * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, 7567ec681f3Smrg * invalid type, invalid size, etc. 7577ec681f3Smrg */ 7587ec681f3SmrgGLAPI GLboolean GLAPIENTRY 7597ec681f3SmrgOSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type, 7607ec681f3Smrg GLsizei width, GLsizei height) 7617ec681f3Smrg{ 7627ec681f3Smrg struct st_api *stapi = get_st_api(); 7637ec681f3Smrg enum pipe_format color_format; 7647ec681f3Smrg 7657ec681f3Smrg if (!osmesa && !buffer) { 7667ec681f3Smrg stapi->make_current(stapi, NULL, NULL, NULL); 7677ec681f3Smrg return GL_TRUE; 7687ec681f3Smrg } 7697ec681f3Smrg 7707ec681f3Smrg if (!osmesa || !buffer || width < 1 || height < 1) { 7717ec681f3Smrg return GL_FALSE; 7727ec681f3Smrg } 7737ec681f3Smrg 7747ec681f3Smrg color_format = osmesa_choose_format(osmesa->format, type); 7757ec681f3Smrg if (color_format == PIPE_FORMAT_NONE) { 7767ec681f3Smrg fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n"); 7777ec681f3Smrg return GL_FALSE; 7787ec681f3Smrg } 7797ec681f3Smrg 7807ec681f3Smrg /* See if we already have a buffer that uses these pixel formats */ 7817ec681f3Smrg if (osmesa->current_buffer && 7827ec681f3Smrg (osmesa->current_buffer->visual.color_format != color_format || 7837ec681f3Smrg osmesa->current_buffer->visual.depth_stencil_format != osmesa->depth_stencil_format || 7847ec681f3Smrg osmesa->current_buffer->visual.accum_format != osmesa->accum_format || 7857ec681f3Smrg osmesa->current_buffer->width != width || 7867ec681f3Smrg osmesa->current_buffer->height != height)) { 7877ec681f3Smrg osmesa_destroy_buffer(osmesa->current_buffer); 7887ec681f3Smrg osmesa->current_buffer = NULL; 7897ec681f3Smrg } 7907ec681f3Smrg 7917ec681f3Smrg if (!osmesa->current_buffer) { 7927ec681f3Smrg osmesa->current_buffer = osmesa_create_buffer(color_format, 7937ec681f3Smrg osmesa->depth_stencil_format, 7947ec681f3Smrg osmesa->accum_format); 7957ec681f3Smrg } 7967ec681f3Smrg 7977ec681f3Smrg struct osmesa_buffer *osbuffer = osmesa->current_buffer; 7987ec681f3Smrg 7997ec681f3Smrg osbuffer->width = width; 8007ec681f3Smrg osbuffer->height = height; 8017ec681f3Smrg osbuffer->map = buffer; 8027ec681f3Smrg 8037ec681f3Smrg osmesa->type = type; 8047ec681f3Smrg 8057ec681f3Smrg stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb); 8067ec681f3Smrg 8077ec681f3Smrg /* XXX: We should probably load the current color value into the buffer here 8087ec681f3Smrg * to match classic swrast behavior (context's fb starts with the contents of 8097ec681f3Smrg * your pixel buffer). 8107ec681f3Smrg */ 8117ec681f3Smrg 8127ec681f3Smrg if (!osmesa->ever_used) { 8137ec681f3Smrg /* one-time init, just postprocessing for now */ 8147ec681f3Smrg boolean any_pp_enabled = FALSE; 8157ec681f3Smrg unsigned i; 8167ec681f3Smrg 8177ec681f3Smrg for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) { 8187ec681f3Smrg if (osmesa->pp_enabled[i]) { 8197ec681f3Smrg any_pp_enabled = TRUE; 8207ec681f3Smrg break; 8217ec681f3Smrg } 8227ec681f3Smrg } 8237ec681f3Smrg 8247ec681f3Smrg if (any_pp_enabled) { 8257ec681f3Smrg osmesa->pp = pp_init(osmesa->stctx->pipe, 8267ec681f3Smrg osmesa->pp_enabled, 8277ec681f3Smrg osmesa->stctx->cso_context, 8287ec681f3Smrg osmesa->stctx); 8297ec681f3Smrg 8307ec681f3Smrg pp_init_fbos(osmesa->pp, width, height); 8317ec681f3Smrg } 8327ec681f3Smrg 8337ec681f3Smrg osmesa->ever_used = TRUE; 8347ec681f3Smrg } 8357ec681f3Smrg 8367ec681f3Smrg return GL_TRUE; 8377ec681f3Smrg} 8387ec681f3Smrg 8397ec681f3Smrg 8407ec681f3Smrg 8417ec681f3SmrgGLAPI OSMesaContext GLAPIENTRY 8427ec681f3SmrgOSMesaGetCurrentContext(void) 8437ec681f3Smrg{ 8447ec681f3Smrg struct st_api *stapi = get_st_api(); 8457ec681f3Smrg struct st_context_iface *st = stapi->get_current(stapi); 8467ec681f3Smrg return st ? (OSMesaContext) st->st_manager_private : NULL; 8477ec681f3Smrg} 8487ec681f3Smrg 8497ec681f3Smrg 8507ec681f3Smrg 8517ec681f3SmrgGLAPI void GLAPIENTRY 8527ec681f3SmrgOSMesaPixelStore(GLint pname, GLint value) 8537ec681f3Smrg{ 8547ec681f3Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 8557ec681f3Smrg 8567ec681f3Smrg switch (pname) { 8577ec681f3Smrg case OSMESA_ROW_LENGTH: 8587ec681f3Smrg osmesa->user_row_length = value; 8597ec681f3Smrg break; 8607ec681f3Smrg case OSMESA_Y_UP: 8617ec681f3Smrg osmesa->y_up = value ? GL_TRUE : GL_FALSE; 8627ec681f3Smrg break; 8637ec681f3Smrg default: 8647ec681f3Smrg fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n"); 8657ec681f3Smrg return; 8667ec681f3Smrg } 8677ec681f3Smrg} 8687ec681f3Smrg 8697ec681f3Smrg 8707ec681f3SmrgGLAPI void GLAPIENTRY 8717ec681f3SmrgOSMesaGetIntegerv(GLint pname, GLint *value) 8727ec681f3Smrg{ 8737ec681f3Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 8747ec681f3Smrg struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL; 8757ec681f3Smrg 8767ec681f3Smrg switch (pname) { 8777ec681f3Smrg case OSMESA_WIDTH: 8787ec681f3Smrg *value = osbuffer ? osbuffer->width : 0; 8797ec681f3Smrg return; 8807ec681f3Smrg case OSMESA_HEIGHT: 8817ec681f3Smrg *value = osbuffer ? osbuffer->height : 0; 8827ec681f3Smrg return; 8837ec681f3Smrg case OSMESA_FORMAT: 8847ec681f3Smrg *value = osmesa->format; 8857ec681f3Smrg return; 8867ec681f3Smrg case OSMESA_TYPE: 8877ec681f3Smrg /* current color buffer's data type */ 8887ec681f3Smrg *value = osmesa->type; 8897ec681f3Smrg return; 8907ec681f3Smrg case OSMESA_ROW_LENGTH: 8917ec681f3Smrg *value = osmesa->user_row_length; 8927ec681f3Smrg return; 8937ec681f3Smrg case OSMESA_Y_UP: 8947ec681f3Smrg *value = osmesa->y_up; 8957ec681f3Smrg return; 8967ec681f3Smrg case OSMESA_MAX_WIDTH: 8977ec681f3Smrg FALLTHROUGH; 8987ec681f3Smrg case OSMESA_MAX_HEIGHT: 8997ec681f3Smrg { 9007ec681f3Smrg struct pipe_screen *screen = get_st_manager()->screen; 9017ec681f3Smrg *value = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); 9027ec681f3Smrg } 9037ec681f3Smrg return; 9047ec681f3Smrg default: 9057ec681f3Smrg fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n"); 9067ec681f3Smrg return; 9077ec681f3Smrg } 9087ec681f3Smrg} 9097ec681f3Smrg 9107ec681f3Smrg 9117ec681f3Smrg/** 9127ec681f3Smrg * Return information about the depth buffer associated with an OSMesa context. 9137ec681f3Smrg * Input: c - the OSMesa context 9147ec681f3Smrg * Output: width, height - size of buffer in pixels 9157ec681f3Smrg * bytesPerValue - bytes per depth value (2 or 4) 9167ec681f3Smrg * buffer - pointer to depth buffer values 9177ec681f3Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 9187ec681f3Smrg */ 9197ec681f3SmrgGLAPI GLboolean GLAPIENTRY 9207ec681f3SmrgOSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height, 9217ec681f3Smrg GLint *bytesPerValue, void **buffer) 9227ec681f3Smrg{ 9237ec681f3Smrg struct osmesa_buffer *osbuffer = c->current_buffer; 9247ec681f3Smrg struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL]; 9257ec681f3Smrg 9267ec681f3Smrg if (!res) { 9277ec681f3Smrg *width = 0; 9287ec681f3Smrg *height = 0; 9297ec681f3Smrg *bytesPerValue = 0; 9307ec681f3Smrg *buffer = NULL; 9317ec681f3Smrg return GL_FALSE; 9327ec681f3Smrg } 9337ec681f3Smrg 9347ec681f3Smrg *width = res->width0; 9357ec681f3Smrg *height = res->height0; 9367ec681f3Smrg *bytesPerValue = util_format_get_blocksize(res->format); 9377ec681f3Smrg 9387ec681f3Smrg if (!c->zs) { 9397ec681f3Smrg c->zs_stride = *width * *bytesPerValue; 9407ec681f3Smrg c->zs = calloc(c->zs_stride, *height); 9417ec681f3Smrg if (!c->zs) 9427ec681f3Smrg return GL_FALSE; 9437ec681f3Smrg 9447ec681f3Smrg osmesa_read_buffer(c, res, c->zs, c->zs_stride, true); 9457ec681f3Smrg } 9467ec681f3Smrg 9477ec681f3Smrg *buffer = c->zs; 9487ec681f3Smrg 9497ec681f3Smrg return GL_TRUE; 9507ec681f3Smrg} 9517ec681f3Smrg 9527ec681f3Smrg 9537ec681f3Smrg/** 9547ec681f3Smrg * Return the color buffer associated with an OSMesa context. 9557ec681f3Smrg * Input: c - the OSMesa context 9567ec681f3Smrg * Output: width, height - size of buffer in pixels 9577ec681f3Smrg * format - the pixel format (OSMESA_FORMAT) 9587ec681f3Smrg * buffer - pointer to color buffer values 9597ec681f3Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 9607ec681f3Smrg */ 9617ec681f3SmrgGLAPI GLboolean GLAPIENTRY 9627ec681f3SmrgOSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width, 9637ec681f3Smrg GLint *height, GLint *format, void **buffer) 9647ec681f3Smrg{ 9657ec681f3Smrg struct osmesa_buffer *osbuffer = osmesa->current_buffer; 9667ec681f3Smrg 9677ec681f3Smrg if (osbuffer) { 9687ec681f3Smrg *width = osbuffer->width; 9697ec681f3Smrg *height = osbuffer->height; 9707ec681f3Smrg *format = osmesa->format; 9717ec681f3Smrg *buffer = osbuffer->map; 9727ec681f3Smrg return GL_TRUE; 9737ec681f3Smrg } 9747ec681f3Smrg else { 9757ec681f3Smrg *width = 0; 9767ec681f3Smrg *height = 0; 9777ec681f3Smrg *format = 0; 9787ec681f3Smrg *buffer = 0; 9797ec681f3Smrg return GL_FALSE; 9807ec681f3Smrg } 9817ec681f3Smrg} 9827ec681f3Smrg 9837ec681f3Smrg 9847ec681f3Smrgstruct name_function 9857ec681f3Smrg{ 9867ec681f3Smrg const char *Name; 9877ec681f3Smrg OSMESAproc Function; 9887ec681f3Smrg}; 9897ec681f3Smrg 9907ec681f3Smrgstatic struct name_function functions[] = { 9917ec681f3Smrg { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, 9927ec681f3Smrg { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, 9937ec681f3Smrg { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs }, 9947ec681f3Smrg { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, 9957ec681f3Smrg { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, 9967ec681f3Smrg { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, 9977ec681f3Smrg { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore }, 9987ec681f3Smrg { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, 9997ec681f3Smrg { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, 10007ec681f3Smrg { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, 10017ec681f3Smrg { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, 10027ec681f3Smrg { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, 10037ec681f3Smrg { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess }, 10047ec681f3Smrg { NULL, NULL } 10057ec681f3Smrg}; 10067ec681f3Smrg 10077ec681f3Smrg 10087ec681f3SmrgGLAPI OSMESAproc GLAPIENTRY 10097ec681f3SmrgOSMesaGetProcAddress(const char *funcName) 10107ec681f3Smrg{ 10117ec681f3Smrg int i; 10127ec681f3Smrg for (i = 0; functions[i].Name; i++) { 10137ec681f3Smrg if (strcmp(functions[i].Name, funcName) == 0) 10147ec681f3Smrg return functions[i].Function; 10157ec681f3Smrg } 10167ec681f3Smrg return _glapi_get_proc_address(funcName); 10177ec681f3Smrg} 10187ec681f3Smrg 10197ec681f3Smrg 10207ec681f3SmrgGLAPI void GLAPIENTRY 10217ec681f3SmrgOSMesaColorClamp(GLboolean enable) 10227ec681f3Smrg{ 10237ec681f3Smrg extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); 10247ec681f3Smrg 10257ec681f3Smrg _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, 10267ec681f3Smrg enable ? GL_TRUE : GL_FIXED_ONLY_ARB); 10277ec681f3Smrg} 10287ec681f3Smrg 10297ec681f3Smrg 10307ec681f3SmrgGLAPI void GLAPIENTRY 10317ec681f3SmrgOSMesaPostprocess(OSMesaContext osmesa, const char *filter, 10327ec681f3Smrg unsigned enable_value) 10337ec681f3Smrg{ 10347ec681f3Smrg if (!osmesa->ever_used) { 10357ec681f3Smrg /* We can only enable/disable postprocess filters before a context 10367ec681f3Smrg * is made current for the first time. 10377ec681f3Smrg */ 10387ec681f3Smrg unsigned i; 10397ec681f3Smrg 10407ec681f3Smrg for (i = 0; i < PP_FILTERS; i++) { 10417ec681f3Smrg if (strcmp(pp_filters[i].name, filter) == 0) { 10427ec681f3Smrg osmesa->pp_enabled[i] = enable_value; 10437ec681f3Smrg return; 10447ec681f3Smrg } 10457ec681f3Smrg } 10467ec681f3Smrg debug_warning("OSMesaPostprocess(unknown filter)\n"); 10477ec681f3Smrg } 10487ec681f3Smrg else { 10497ec681f3Smrg debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n"); 10507ec681f3Smrg } 10517ec681f3Smrg} 1052