Files
banan-os/ports/mesa/patches/0001-add-back-osmesa.patch
Bananymous e78fcf63b6 ports: Update mesa 25.0.7->26.1.4
This required bringing back osmesa code from 25.0.7 which was the last
version where it was supported. Seems to work fine though
2026-07-07 04:36:55 +03:00

1598 lines
49 KiB
Diff

diff -ruN mesa-26.1.4/include/GL/osmesa.h mesa-26.1.4-banan_os/include/GL/osmesa.h
--- mesa-26.1.4/include/GL/osmesa.h 1970-01-01 02:00:00.000000000 +0200
+++ mesa-26.1.4-banan_os/include/GL/osmesa.h 2026-07-05 04:20:13.927530490 +0300
@@ -0,0 +1,332 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Mesa Off-Screen rendering interface.
+ *
+ * This is an operating system and window system independent interface to
+ * Mesa which allows one to render images into a client-supplied buffer in
+ * main memory. Such images may manipulated or saved in whatever way the
+ * client wants.
+ *
+ * These are the API functions:
+ * OSMesaCreateContext - create a new Off-Screen Mesa rendering context
+ * OSMesaMakeCurrent - bind an OSMesaContext to a client's image buffer
+ * and make the specified context the current one.
+ * OSMesaDestroyContext - destroy an OSMesaContext
+ * OSMesaGetCurrentContext - return thread's current context ID
+ * OSMesaPixelStore - controls how pixels are stored in image buffer
+ * OSMesaGetIntegerv - return OSMesa state parameters
+ *
+ *
+ * The limits on the width and height of an image buffer can be retrieved
+ * via OSMesaGetIntegerv(OSMESA_MAX_WIDTH/OSMESA_MAX_HEIGHT).
+ */
+
+
+#ifndef OSMESA_H
+#define OSMESA_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <GL/gl.h>
+
+
+#define OSMESA_MAJOR_VERSION 11
+#define OSMESA_MINOR_VERSION 2
+#define OSMESA_PATCH_VERSION 0
+
+
+
+/*
+ * Values for the format parameter of OSMesaCreateContext()
+ * New in version 2.0.
+ */
+#define OSMESA_COLOR_INDEX GL_COLOR_INDEX
+#define OSMESA_RGBA GL_RGBA
+#define OSMESA_BGRA 0x1
+#define OSMESA_ARGB 0x2
+#define OSMESA_RGB GL_RGB
+#define OSMESA_BGR 0x4
+#define OSMESA_RGB_565 0x5
+
+
+/*
+ * OSMesaPixelStore() parameters:
+ * New in version 2.0.
+ */
+#define OSMESA_ROW_LENGTH 0x10
+#define OSMESA_Y_UP 0x11
+
+
+/*
+ * Accepted by OSMesaGetIntegerv:
+ */
+#define OSMESA_WIDTH 0x20
+#define OSMESA_HEIGHT 0x21
+#define OSMESA_FORMAT 0x22
+#define OSMESA_TYPE 0x23
+#define OSMESA_MAX_WIDTH 0x24 /* new in 4.0 */
+#define OSMESA_MAX_HEIGHT 0x25 /* new in 4.0 */
+
+/*
+ * Accepted in OSMesaCreateContextAttrib's attribute list.
+ */
+#define OSMESA_DEPTH_BITS 0x30
+#define OSMESA_STENCIL_BITS 0x31
+#define OSMESA_ACCUM_BITS 0x32
+#define OSMESA_PROFILE 0x33
+#define OSMESA_CORE_PROFILE 0x34
+#define OSMESA_COMPAT_PROFILE 0x35
+#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
+#define OSMESA_CONTEXT_MINOR_VERSION 0x37
+
+
+typedef struct osmesa_context *OSMesaContext;
+
+
+/*
+ * Create an Off-Screen Mesa rendering context. The only attribute needed is
+ * an RGBA vs Color-Index mode flag.
+ *
+ * Input: format - one of OSMESA_COLOR_INDEX, OSMESA_RGBA, OSMESA_BGRA,
+ * OSMESA_ARGB, OSMESA_RGB, or OSMESA_BGR.
+ * sharelist - specifies another OSMesaContext with which to share
+ * display lists. NULL indicates no sharing.
+ * Return: an OSMesaContext or 0 if error
+ */
+GLAPI OSMesaContext APIENTRY
+OSMesaCreateContext( GLenum format, OSMesaContext sharelist );
+
+
+
+/*
+ * Create an Off-Screen Mesa rendering context and specify desired
+ * size of depth buffer, stencil buffer and accumulation buffer.
+ * If you specify zero for depthBits, stencilBits, accumBits you
+ * can save some memory.
+ *
+ * New in Mesa 3.5
+ */
+GLAPI OSMesaContext APIENTRY
+OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
+ GLint accumBits, OSMesaContext sharelist);
+
+
+/*
+ * Create an Off-Screen Mesa rendering context with attribute list.
+ * The list is composed of (attribute, value) pairs and terminated with
+ * attribute==0. Supported Attributes:
+ *
+ * Attributes Values
+ * --------------------------------------------------------------------------
+ * OSMESA_FORMAT OSMESA_RGBA*, OSMESA_BGRA, OSMESA_ARGB, etc.
+ * OSMESA_DEPTH_BITS 0*, 16, 24, 32
+ * OSMESA_STENCIL_BITS 0*, 8
+ * OSMESA_ACCUM_BITS 0*, 16
+ * OSMESA_PROFILE OSMESA_COMPAT_PROFILE*, OSMESA_CORE_PROFILE
+ * OSMESA_CONTEXT_MAJOR_VERSION 1*, 2, 3
+ * OSMESA_CONTEXT_MINOR_VERSION 0+
+ *
+ * Note: * = default value
+ *
+ * We return a context version >= what's specified by OSMESA_CONTEXT_MAJOR/
+ * MINOR_VERSION for the given profile. For example, if you request a GL 1.4
+ * compat profile, you might get a GL 3.0 compat profile.
+ * Otherwise, null is returned if the version/profile is not supported.
+ *
+ * New in Mesa 11.2
+ */
+GLAPI OSMesaContext APIENTRY
+OSMesaCreateContextAttribs( const int *attribList, OSMesaContext sharelist );
+
+
+
+/*
+ * Destroy an Off-Screen Mesa rendering context.
+ *
+ * Input: ctx - the context to destroy
+ */
+GLAPI void APIENTRY
+OSMesaDestroyContext( OSMesaContext ctx );
+
+
+
+/*
+ * Bind an OSMesaContext to an image buffer. The image buffer is just a
+ * block of memory which the client provides. Its size must be at least
+ * as large as width*height*sizeof(type). Its address should be a multiple
+ * of 4 if using RGBA mode.
+ *
+ * Image data is stored in the order of glDrawPixels: row-major order
+ * with the lower-left image pixel stored in the first array position
+ * (ie. bottom-to-top).
+ *
+ * Since the only type initially supported is GL_UNSIGNED_BYTE, if the
+ * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA
+ * value. If the context is in color indexed mode, each pixel will be
+ * stored as a 1-byte value.
+ *
+ * If the context's viewport hasn't been initialized yet, it will now be
+ * initialized to (0,0,width,height).
+ *
+ * Input: ctx - the rendering context
+ * buffer - the image buffer memory
+ * type - data type for pixel components, only GL_UNSIGNED_BYTE
+ * supported now
+ * width, height - size of image buffer in pixels, at least 1
+ * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
+ * invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1,
+ * width>internal limit or height>internal limit.
+ */
+GLAPI GLboolean APIENTRY
+OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
+ GLsizei width, GLsizei height );
+
+
+
+
+/*
+ * Return the current Off-Screen Mesa rendering context handle.
+ */
+GLAPI OSMesaContext APIENTRY
+OSMesaGetCurrentContext( void );
+
+
+
+/*
+ * Set pixel store/packing parameters for the current context.
+ * This is similar to glPixelStore.
+ * Input: pname - OSMESA_ROW_LENGTH
+ * specify actual pixels per row in image buffer
+ * 0 = same as image width (default)
+ * OSMESA_Y_UP
+ * zero = Y coordinates increase downward
+ * non-zero = Y coordinates increase upward (default)
+ * value - the value for the parameter pname
+ *
+ * New in version 2.0.
+ */
+GLAPI void APIENTRY
+OSMesaPixelStore( GLint pname, GLint value );
+
+
+
+/*
+ * Return an integer value like glGetIntegerv.
+ * Input: pname -
+ * OSMESA_WIDTH return current image width
+ * OSMESA_HEIGHT return current image height
+ * OSMESA_FORMAT return image format
+ * OSMESA_TYPE return color component data type
+ * OSMESA_ROW_LENGTH return row length in pixels
+ * OSMESA_Y_UP returns 1 or 0 to indicate Y axis direction
+ * value - pointer to integer in which to return result.
+ */
+GLAPI void APIENTRY
+OSMesaGetIntegerv( GLint pname, GLint *value );
+
+
+
+/*
+ * Return the depth buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * bytesPerValue - bytes per depth value (2 or 4)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ *
+ * New in Mesa 2.4.
+ */
+GLAPI GLboolean APIENTRY
+OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
+ GLint *bytesPerValue, void **buffer );
+
+
+
+/*
+ * Return the color buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * format - buffer format (OSMESA_FORMAT)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ *
+ * New in Mesa 3.3.
+ */
+GLAPI GLboolean APIENTRY
+OSMesaGetColorBuffer( OSMesaContext c, GLint *width, GLint *height,
+ GLint *format, void **buffer );
+
+
+
+/**
+ * This typedef is new in Mesa 6.3.
+ */
+typedef void (*OSMESAproc)();
+
+
+/*
+ * Return pointer to the named function.
+ * New in Mesa 4.1
+ * Return OSMESAproc in 6.3.
+ */
+GLAPI OSMESAproc APIENTRY
+OSMesaGetProcAddress( const char *funcName );
+
+
+
+/**
+ * Enable/disable color clamping, off by default.
+ * New in Mesa 6.4.2
+ */
+GLAPI void APIENTRY
+OSMesaColorClamp(GLboolean enable);
+
+
+/**
+ * Enable/disable Gallium post-process filters.
+ * This should be called after a context is created, but before it is
+ * made current for the first time. After a context has been made
+ * current, this function has no effect.
+ * If the enable_value param is zero, the filter is disabled. Otherwise
+ * the filter is enabled, and the value may control the filter's quality.
+ * New in Mesa 10.0
+ */
+GLAPI void APIENTRY
+OSMesaPostprocess(OSMesaContext osmesa, const char *filter,
+ unsigned enable_value);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff -ruN mesa-26.1.4/include/meson.build mesa-26.1.4-banan_os/include/meson.build
--- mesa-26.1.4/include/meson.build 2026-07-01 17:16:13.000000000 +0300
+++ mesa-26.1.4-banan_os/include/meson.build 2026-07-05 04:20:13.934374363 +0300
@@ -78,6 +78,10 @@
)
endif
+if with_osmesa
+ install_headers('GL/osmesa.h', subdir : 'GL')
+endif
+
if with_dri
install_headers('GL/internal/dri_interface.h', subdir : 'GL/internal')
endif
diff -ruN mesa-26.1.4/meson.build mesa-26.1.4-banan_os/meson.build
--- mesa-26.1.4/meson.build 2026-07-01 17:16:13.000000000 +0300
+++ mesa-26.1.4-banan_os/meson.build 2026-07-05 04:20:13.894859382 +0300
@@ -107,6 +107,7 @@
with_aco_tests = get_option('build-aco-tests')
with_glx_read_only_text = get_option('glx-read-only-text')
with_glx_direct = get_option('glx-direct')
+with_osmesa = get_option('osmesa')
with_vulkan_overlay_layer = get_option('vulkan-layers').contains('overlay')
with_vulkan_device_select_layer = get_option('vulkan-layers').contains('device-select')
with_vulkan_screenshot_layer = get_option('vulkan-layers').contains('screenshot')
@@ -2152,6 +2153,17 @@
pre_args += '-DHAVE_LIBUNWIND'
endif
+if with_osmesa
+ if not with_gallium_swrast
+ error('OSMesa gallium requires gallium softpipe or llvmpipe.')
+ endif
+ if host_machine.system() == 'windows'
+ osmesa_lib_name = 'osmesa'
+ else
+ osmesa_lib_name = 'OSMesa'
+ endif
+endif
+
# TODO: symbol mangling
with_wayland_bind_display = with_platform_wayland and get_option('legacy-wayland').contains('bind-wayland-display')
@@ -2567,6 +2579,7 @@
gallium_frontends += 'rusticl'
endif
gallium_summary += {'Frontends': gallium_frontends}
+ gallium_summary += {'Off-screen rendering (OSMesa)': with_osmesa ? 'lib' + osmesa_lib_name : false}
gallium_summary += {'HUD lm-sensors': dep_lmsensors.found()}
endif
summary(gallium_summary, section: 'Gallium', bool_yn: true, list_sep: ' ')
diff -ruN mesa-26.1.4/meson.options mesa-26.1.4-banan_os/meson.options
--- mesa-26.1.4/meson.options 2026-07-01 17:16:13.000000000 +0300
+++ mesa-26.1.4-banan_os/meson.options 2026-07-05 04:20:13.784091541 +0300
@@ -547,6 +547,13 @@
)
option(
+ 'osmesa',
+ type : 'boolean',
+ value : false,
+ description : 'Build OSmesa.'
+)
+
+option(
'tools',
type : 'array',
value : [],
diff -ruN mesa-26.1.4/src/gallium/frontends/osmesa/meson.build mesa-26.1.4-banan_os/src/gallium/frontends/osmesa/meson.build
--- mesa-26.1.4/src/gallium/frontends/osmesa/meson.build 1970-01-01 02:00:00.000000000 +0200
+++ mesa-26.1.4-banan_os/src/gallium/frontends/osmesa/meson.build 2026-07-05 04:20:14.131684982 +0300
@@ -0,0 +1,19 @@
+# Copyright © 2017-2018 Intel Corporation
+# SPDX-License-Identifier: MIT
+
+osmesa_st_c_args = []
+if with_platform_windows
+ if not with_shared_glapi
+ osmesa_st_c_args += ['-D_GLAPI_NO_EXPORTS']
+ endif
+endif
+
+libosmesa_st = static_library(
+ 'osmesa_st',
+ 'osmesa.c',
+ c_args : osmesa_st_c_args,
+ include_directories : [
+ inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mesa,
+ ],
+ dependencies : [idep_mesautil],
+)
diff -ruN mesa-26.1.4/src/gallium/frontends/osmesa/osmesa.c mesa-26.1.4-banan_os/src/gallium/frontends/osmesa/osmesa.c
--- mesa-26.1.4/src/gallium/frontends/osmesa/osmesa.c 1970-01-01 02:00:00.000000000 +0200
+++ mesa-26.1.4-banan_os/src/gallium/frontends/osmesa/osmesa.c 2026-07-05 04:20:14.131719693 +0300
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2013 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Off-Screen rendering into client memory.
+ * OpenGL gallium frontend for softpipe and llvmpipe.
+ *
+ * Notes:
+ *
+ * If Gallium is built with LLVM support we use the llvmpipe driver.
+ * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable
+ * may be set to "softpipe" or "llvmpipe" to override.
+ *
+ * With softpipe we could render directly into the user's buffer by using a
+ * display target resource. However, softpipe doesn't support "upside-down"
+ * rendering which would be needed for the OSMESA_Y_UP=TRUE case.
+ *
+ * With llvmpipe we could only render directly into the user's buffer when its
+ * width and height is a multiple of the tile size (64 pixels).
+ *
+ * Because of these constraints we always render into ordinary resources then
+ * copy the results to the user's buffer in the flush_front() function which
+ * is called when the app calls glFlush/Finish.
+ *
+ * In general, the OSMesa interface is pretty ugly and not a good match
+ * for Gallium. But we're interested in doing the best we can to preserve
+ * application portability. With a little work we could come up with a
+ * much nicer, new off-screen Gallium interface...
+ */
+
+/**
+ * The following block is for avoid windows.h to be included
+ * and osmesa require APIENTRY to be defined
+ */
+#include "util/glheader.h"
+#ifndef APIENTRY
+#define APIENTRY GLAPIENTRY
+#endif
+#include "GL/osmesa.h"
+
+#include <stdio.h>
+#include <c11/threads.h>
+
+#include "state_tracker/st_context.h"
+
+#include "glapi/glapi/glapi.h" /* for OSMesaGetProcAddress below */
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+
+#include "util/u_atomic.h"
+#include "util/box.h"
+#include "util/u_debug.h"
+#include "util/format/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "postprocess/filters.h"
+#include "postprocess/postprocess.h"
+
+#include "frontend/api.h"
+
+
+
+extern struct pipe_screen *
+osmesa_create_screen(void);
+
+
+
+struct osmesa_buffer
+{
+ struct pipe_frontend_drawable base;
+ struct st_visual visual;
+ unsigned width, height;
+
+ struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
+
+ void *map;
+
+ struct osmesa_buffer *next; /**< next in linked list */
+};
+
+
+struct osmesa_context
+{
+ struct st_context *st;
+
+ bool ever_used; /*< Has this context ever been current? */
+
+ struct osmesa_buffer *current_buffer;
+
+ /* Storage for depth/stencil, if the user has requested access. The backing
+ * driver always has its own storage for the actual depth/stencil, which we
+ * have to transfer in and out.
+ */
+ void *zs;
+ unsigned zs_stride;
+
+ enum pipe_format depth_stencil_format, accum_format;
+
+ GLenum format; /*< User-specified context format */
+ GLenum type; /*< Buffer's data type */
+ GLint user_row_length; /*< user-specified number of pixels per row */
+ GLboolean y_up; /*< TRUE -> Y increases upward */
+ /*< FALSE -> Y increases downward */
+
+ /** Which postprocessing filters are enabled. */
+ unsigned pp_enabled[PP_FILTERS];
+ struct pp_queue_t *pp;
+};
+
+/**
+ * Called from the ST manager.
+ */
+static int
+osmesa_st_get_param(struct pipe_frontend_screen *fscreen, enum st_manager_param param)
+{
+ /* no-op */
+ return 0;
+}
+
+static struct pipe_frontend_screen *global_fscreen = NULL;
+
+static void
+destroy_st_manager(void)
+{
+ if (global_fscreen) {
+ if (global_fscreen->screen)
+ global_fscreen->screen->destroy(global_fscreen->screen);
+ FREE(global_fscreen);
+ }
+}
+
+static void
+create_st_manager(void)
+{
+ if (atexit(destroy_st_manager) != 0)
+ return;
+
+ global_fscreen = CALLOC_STRUCT(pipe_frontend_screen);
+ if (global_fscreen) {
+ global_fscreen->screen = osmesa_create_screen();
+ global_fscreen->get_param = osmesa_st_get_param;
+ global_fscreen->get_egl_image = NULL;
+ }
+}
+
+/**
+ * Create/return a singleton st_manager object.
+ */
+static struct pipe_frontend_screen *
+get_st_manager(void)
+{
+ static once_flag create_once_flag = ONCE_FLAG_INIT;
+
+ call_once(&create_once_flag, create_st_manager);
+
+ return global_fscreen;
+}
+
+/* Reads the color or depth buffer from the backing context to either the user storage
+ * (color buffer) or our temporary (z/s)
+ */
+static void
+osmesa_read_buffer(OSMesaContext osmesa, struct pipe_resource *res, void *dst,
+ int dst_stride, bool y_up)
+{
+ struct pipe_context *pipe = osmesa->st->pipe;
+
+ struct pipe_box box;
+ u_box_2d(0, 0, res->width0, res->height0, &box);
+
+ struct pipe_transfer *transfer = NULL;
+ uint8_t *src = pipe->texture_map(pipe, res, 0, PIPE_MAP_READ, &box,
+ &transfer);
+
+ /*
+ * Copy the color buffer from the resource to the user's buffer.
+ */
+
+ if (y_up) {
+ /* need to flip image upside down */
+ dst = (uint8_t *)dst + (res->height0 - 1) * dst_stride;
+ dst_stride = -dst_stride;
+ }
+
+ unsigned bpp = util_format_get_blocksize(res->format);
+ for (unsigned y = 0; y < res->height0; y++)
+ {
+ memcpy(dst, src, bpp * res->width0);
+ dst = (uint8_t *)dst + dst_stride;
+ src += transfer->stride;
+ }
+
+ pipe->texture_unmap(pipe, transfer);
+}
+
+
+/**
+ * Given an OSMESA_x format and a GL_y type, return the best
+ * matching PIPE_FORMAT_z.
+ * Note that we can't exactly match all user format/type combinations
+ * with gallium formats. If we find this to be a problem, we can
+ * implement more elaborate format/type conversion in the flush_front()
+ * function.
+ */
+static enum pipe_format
+osmesa_choose_format(GLenum format, GLenum type)
+{
+ switch (format) {
+ case OSMESA_RGBA:
+ if (type == GL_UNSIGNED_BYTE) {
+#if UTIL_ARCH_LITTLE_ENDIAN
+ return PIPE_FORMAT_R8G8B8A8_UNORM;
+#else
+ return PIPE_FORMAT_A8B8G8R8_UNORM;
+#endif
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ return PIPE_FORMAT_R16G16B16A16_UNORM;
+ }
+ else if (type == GL_FLOAT) {
+ return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+ else {
+ return PIPE_FORMAT_NONE;
+ }
+ break;
+ case OSMESA_BGRA:
+ if (type == GL_UNSIGNED_BYTE) {
+#if UTIL_ARCH_LITTLE_ENDIAN
+ return PIPE_FORMAT_B8G8R8A8_UNORM;
+#else
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+#endif
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ return PIPE_FORMAT_R16G16B16A16_UNORM;
+ }
+ else if (type == GL_FLOAT) {
+ return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+ else {
+ return PIPE_FORMAT_NONE;
+ }
+ break;
+ case OSMESA_ARGB:
+ if (type == GL_UNSIGNED_BYTE) {
+#if UTIL_ARCH_LITTLE_ENDIAN
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+#else
+ return PIPE_FORMAT_B8G8R8A8_UNORM;
+#endif
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ return PIPE_FORMAT_R16G16B16A16_UNORM;
+ }
+ else if (type == GL_FLOAT) {
+ return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+ else {
+ return PIPE_FORMAT_NONE;
+ }
+ break;
+ case OSMESA_RGB:
+ if (type == GL_UNSIGNED_BYTE) {
+ return PIPE_FORMAT_R8G8B8_UNORM;
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ return PIPE_FORMAT_R16G16B16_UNORM;
+ }
+ else if (type == GL_FLOAT) {
+ return PIPE_FORMAT_R32G32B32_FLOAT;
+ }
+ else {
+ return PIPE_FORMAT_NONE;
+ }
+ break;
+ case OSMESA_BGR:
+ /* No gallium format for this one */
+ return PIPE_FORMAT_NONE;
+ case OSMESA_RGB_565:
+ if (type != GL_UNSIGNED_SHORT_5_6_5)
+ return PIPE_FORMAT_NONE;
+ return PIPE_FORMAT_B5G6R5_UNORM;
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+
+/**
+ * Initialize an st_visual object.
+ */
+static void
+osmesa_init_st_visual(struct st_visual *vis,
+ enum pipe_format color_format,
+ enum pipe_format ds_format,
+ enum pipe_format accum_format)
+{
+ vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
+
+ if (ds_format != PIPE_FORMAT_NONE)
+ vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
+ if (accum_format != PIPE_FORMAT_NONE)
+ vis->buffer_mask |= ST_ATTACHMENT_ACCUM;
+
+ vis->color_format = color_format;
+ vis->depth_stencil_format = ds_format;
+ vis->accum_format = accum_format;
+ vis->samples = 1;
+}
+
+
+/**
+ * Return the osmesa_buffer that corresponds to an pipe_frontend_drawable.
+ */
+static inline struct osmesa_buffer *
+drawable_to_osbuffer(struct pipe_frontend_drawable *drawable)
+{
+ return (struct osmesa_buffer *)drawable;
+}
+
+
+/**
+ * Called via glFlush/glFinish. This is where we copy the contents
+ * of the driver's color buffer into the user-specified buffer.
+ */
+static bool
+osmesa_st_framebuffer_flush_front(struct st_context *st,
+ struct pipe_frontend_drawable *drawable,
+ enum st_attachment_type statt)
+{
+ OSMesaContext osmesa = OSMesaGetCurrentContext();
+ struct osmesa_buffer *osbuffer = drawable_to_osbuffer(drawable);
+ struct pipe_resource *res = osbuffer->textures[statt];
+ unsigned bpp;
+ int dst_stride;
+
+ if (statt != ST_ATTACHMENT_FRONT_LEFT)
+ return false;
+
+ if (osmesa->pp) {
+ struct pipe_resource *zsbuf = NULL;
+ unsigned i;
+
+ /* Find the z/stencil buffer if there is one */
+ for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) {
+ struct pipe_resource *res = osbuffer->textures[i];
+ if (res) {
+ const struct util_format_description *desc =
+ util_format_description(res->format);
+
+ if (util_format_has_depth(desc)) {
+ zsbuf = res;
+ break;
+ }
+ }
+ }
+
+ /* run the postprocess stage(s) */
+ pp_run(osmesa->pp, res, res, zsbuf);
+ }
+
+ /* Snapshot the color buffer to the user's buffer. */
+ bpp = util_format_get_blocksize(osbuffer->visual.color_format);
+ if (osmesa->user_row_length)
+ dst_stride = bpp * osmesa->user_row_length;
+ else
+ dst_stride = bpp * osbuffer->width;
+
+ osmesa_read_buffer(osmesa, res, osbuffer->map, dst_stride, osmesa->y_up);
+
+ /* If the user has requested the Z/S buffer, then snapshot that one too. */
+ if (osmesa->zs) {
+ osmesa_read_buffer(osmesa, osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL],
+ osmesa->zs, osmesa->zs_stride, true);
+ }
+
+ return true;
+}
+
+
+/**
+ * Called by the st manager to validate the framebuffer (allocate
+ * its resources).
+ */
+static bool
+osmesa_st_framebuffer_validate(struct st_context *st,
+ struct pipe_frontend_drawable *drawable,
+ const enum st_attachment_type *statts,
+ unsigned count,
+ struct pipe_resource **out,
+ struct pipe_resource **resolve)
+{
+ struct pipe_screen *screen = get_st_manager()->screen;
+ enum st_attachment_type i;
+ struct osmesa_buffer *osbuffer = drawable_to_osbuffer(drawable);
+ struct pipe_resource templat;
+
+ memset(&templat, 0, sizeof(templat));
+ templat.target = PIPE_TEXTURE_RECT;
+ templat.format = 0; /* setup below */
+ templat.last_level = 0;
+ templat.width0 = osbuffer->width;
+ templat.height0 = osbuffer->height;
+ templat.depth0 = 1;
+ templat.array_size = 1;
+ templat.usage = PIPE_USAGE_DEFAULT;
+ templat.bind = 0; /* setup below */
+ templat.flags = 0;
+
+ for (i = 0; i < count; i++) {
+ enum pipe_format format = PIPE_FORMAT_NONE;
+ unsigned bind = 0;
+
+ /*
+ * At this time, we really only need to handle the front-left color
+ * attachment, since that's all we specified for the visual in
+ * osmesa_init_st_visual().
+ */
+ if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
+ format = osbuffer->visual.color_format;
+ bind = PIPE_BIND_RENDER_TARGET;
+ }
+ else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
+ format = osbuffer->visual.depth_stencil_format;
+ bind = PIPE_BIND_DEPTH_STENCIL;
+ }
+ else if (statts[i] == ST_ATTACHMENT_ACCUM) {
+ format = osbuffer->visual.accum_format;
+ bind = PIPE_BIND_RENDER_TARGET;
+ }
+ else {
+ debug_warning("Unexpected attachment type in "
+ "osmesa_st_framebuffer_validate()");
+ }
+
+ templat.format = format;
+ templat.bind = bind;
+ pipe_resource_reference(&out[i], NULL);
+ out[i] = osbuffer->textures[statts[i]] =
+ screen->resource_create(screen, &templat);
+ }
+
+ return true;
+}
+
+static uint32_t osmesa_fb_ID = 0;
+
+
+/**
+ * Create new buffer and add to linked list.
+ */
+static struct osmesa_buffer *
+osmesa_create_buffer(enum pipe_format color_format,
+ enum pipe_format ds_format,
+ enum pipe_format accum_format)
+{
+ struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer);
+ if (osbuffer) {
+ osbuffer->base.flush_front = osmesa_st_framebuffer_flush_front;
+ osbuffer->base.validate = osmesa_st_framebuffer_validate;
+ p_atomic_set(&osbuffer->base.stamp, 1);
+ osbuffer->base.ID = p_atomic_inc_return(&osmesa_fb_ID);
+ osbuffer->base.fscreen = get_st_manager();
+ osbuffer->base.visual = &osbuffer->visual;
+
+ osmesa_init_st_visual(&osbuffer->visual, color_format,
+ ds_format, accum_format);
+ }
+
+ return osbuffer;
+}
+
+
+static void
+osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
+{
+ /*
+ * Notify the state manager that the associated framebuffer interface
+ * is no longer valid.
+ */
+ st_api_destroy_drawable(&osbuffer->base);
+
+ FREE(osbuffer);
+}
+
+
+
+/**********************************************************************/
+/***** Public Functions *****/
+/**********************************************************************/
+
+
+/**
+ * Create an Off-Screen Mesa rendering context. The only attribute needed is
+ * an RGBA vs Color-Index mode flag.
+ *
+ * Input: format - Must be GL_RGBA
+ * sharelist - specifies another OSMesaContext with which to share
+ * display lists. NULL indicates no sharing.
+ * Return: an OSMesaContext or 0 if error
+ */
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaCreateContext(GLenum format, OSMesaContext sharelist)
+{
+ return OSMesaCreateContextExt(format, 24, 8, 0, sharelist);
+}
+
+
+/**
+ * New in Mesa 3.5
+ *
+ * Create context and specify size of ancillary buffers.
+ */
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits,
+ GLint accumBits, OSMesaContext sharelist)
+{
+ int attribs[100], n = 0;
+
+ attribs[n++] = OSMESA_FORMAT;
+ attribs[n++] = format;
+ attribs[n++] = OSMESA_DEPTH_BITS;
+ attribs[n++] = depthBits;
+ attribs[n++] = OSMESA_STENCIL_BITS;
+ attribs[n++] = stencilBits;
+ attribs[n++] = OSMESA_ACCUM_BITS;
+ attribs[n++] = accumBits;
+ attribs[n++] = 0;
+
+ return OSMesaCreateContextAttribs(attribs, sharelist);
+}
+
+
+/**
+ * New in Mesa 11.2
+ *
+ * Create context with attribute list.
+ */
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
+{
+ OSMesaContext osmesa;
+ struct st_context *st_shared;
+ enum st_context_error st_error = 0;
+ struct st_context_attribs attribs;
+ GLenum format = GL_RGBA;
+ int depthBits = 0, stencilBits = 0, accumBits = 0;
+ int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0;
+ int i;
+
+ if (sharelist) {
+ st_shared = sharelist->st;
+ }
+ else {
+ st_shared = NULL;
+ }
+
+ for (i = 0; attribList[i]; i += 2) {
+ switch (attribList[i]) {
+ case OSMESA_FORMAT:
+ format = attribList[i+1];
+ switch (format) {
+ case OSMESA_COLOR_INDEX:
+ case OSMESA_RGBA:
+ case OSMESA_BGRA:
+ case OSMESA_ARGB:
+ case OSMESA_RGB:
+ case OSMESA_BGR:
+ case OSMESA_RGB_565:
+ /* legal */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ case OSMESA_DEPTH_BITS:
+ depthBits = attribList[i+1];
+ if (depthBits < 0)
+ return NULL;
+ break;
+ case OSMESA_STENCIL_BITS:
+ stencilBits = attribList[i+1];
+ if (stencilBits < 0)
+ return NULL;
+ break;
+ case OSMESA_ACCUM_BITS:
+ accumBits = attribList[i+1];
+ if (accumBits < 0)
+ return NULL;
+ break;
+ case OSMESA_PROFILE:
+ profile = attribList[i+1];
+ if (profile != OSMESA_CORE_PROFILE &&
+ profile != OSMESA_COMPAT_PROFILE)
+ return NULL;
+ break;
+ case OSMESA_CONTEXT_MAJOR_VERSION:
+ version_major = attribList[i+1];
+ if (version_major < 1)
+ return NULL;
+ break;
+ case OSMESA_CONTEXT_MINOR_VERSION:
+ version_minor = attribList[i+1];
+ if (version_minor < 0)
+ return NULL;
+ break;
+ case 0:
+ /* end of list */
+ break;
+ default:
+ fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n");
+ return NULL;
+ }
+ }
+
+ osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
+ if (!osmesa)
+ return NULL;
+
+ /* Choose depth/stencil/accum buffer formats */
+ if (accumBits > 0) {
+ osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM;
+ }
+ if (depthBits > 0 && stencilBits > 0) {
+ osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
+ }
+ else if (stencilBits > 0) {
+ osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT;
+ }
+ else if (depthBits >= 24) {
+ osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
+ }
+ else if (depthBits >= 16) {
+ osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
+ }
+
+ /*
+ * Create the rendering context
+ */
+ memset(&attribs, 0, sizeof(attribs));
+ attribs.profile = (profile == OSMESA_CORE_PROFILE)
+ ? API_OPENGL_CORE : API_OPENGL_COMPAT;
+ attribs.major = version_major;
+ attribs.minor = version_minor;
+ attribs.flags = 0; /* ST_CONTEXT_FLAG_x */
+ attribs.options.force_glsl_extensions_warn = false;
+ attribs.options.disable_blend_func_extended = false;
+ attribs.options.disable_glsl_line_continuations = false;
+ attribs.options.force_glsl_version = 0;
+
+ osmesa_init_st_visual(&attribs.visual,
+ PIPE_FORMAT_NONE,
+ osmesa->depth_stencil_format,
+ osmesa->accum_format);
+
+ osmesa->st = st_api_create_context(get_st_manager(),
+ &attribs, &st_error, st_shared);
+ if (!osmesa->st) {
+ FREE(osmesa);
+ return NULL;
+ }
+
+ osmesa->st->frontend_context = osmesa;
+
+ osmesa->format = format;
+ osmesa->user_row_length = 0;
+ osmesa->y_up = GL_TRUE;
+
+ return osmesa;
+}
+
+
+
+/**
+ * Destroy an Off-Screen Mesa rendering context.
+ *
+ * \param osmesa the context to destroy
+ */
+GLAPI void GLAPIENTRY
+OSMesaDestroyContext(OSMesaContext osmesa)
+{
+ if (osmesa) {
+ pp_free(osmesa->pp);
+ st_destroy_context(osmesa->st);
+ free(osmesa->zs);
+ FREE(osmesa);
+ }
+}
+
+
+/**
+ * Bind an OSMesaContext to an image buffer. The image buffer is just a
+ * block of memory which the client provides. Its size must be at least
+ * as large as width*height*pixelSize. Its address should be a multiple
+ * of 4 if using RGBA mode.
+ *
+ * By default, image data is stored in the order of glDrawPixels: row-major
+ * order with the lower-left image pixel stored in the first array position
+ * (ie. bottom-to-top).
+ *
+ * If the context's viewport hasn't been initialized yet, it will now be
+ * initialized to (0,0,width,height).
+ *
+ * Input: osmesa - the rendering context
+ * buffer - the image buffer memory
+ * type - data type for pixel components
+ * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT
+ * or GL_FLOAT.
+ * width, height - size of image buffer in pixels, at least 1
+ * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
+ * invalid type, invalid size, etc.
+ */
+GLAPI GLboolean GLAPIENTRY
+OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
+ GLsizei width, GLsizei height)
+{
+ enum pipe_format color_format;
+
+ if (!osmesa && !buffer) {
+ st_api_make_current(NULL, NULL, NULL);
+ return GL_TRUE;
+ }
+
+ if (!osmesa || !buffer || width < 1 || height < 1) {
+ return GL_FALSE;
+ }
+
+ color_format = osmesa_choose_format(osmesa->format, type);
+ if (color_format == PIPE_FORMAT_NONE) {
+ fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n");
+ return GL_FALSE;
+ }
+
+ /* See if we already have a buffer that uses these pixel formats */
+ if (osmesa->current_buffer &&
+ (osmesa->current_buffer->visual.color_format != color_format ||
+ osmesa->current_buffer->visual.depth_stencil_format != osmesa->depth_stencil_format ||
+ osmesa->current_buffer->visual.accum_format != osmesa->accum_format ||
+ osmesa->current_buffer->width != width ||
+ osmesa->current_buffer->height != height)) {
+ osmesa_destroy_buffer(osmesa->current_buffer);
+ osmesa->current_buffer = NULL;
+ }
+
+ if (!osmesa->current_buffer) {
+ osmesa->current_buffer = osmesa_create_buffer(color_format,
+ osmesa->depth_stencil_format,
+ osmesa->accum_format);
+ }
+
+ struct osmesa_buffer *osbuffer = osmesa->current_buffer;
+
+ osbuffer->width = width;
+ osbuffer->height = height;
+ osbuffer->map = buffer;
+
+ osmesa->type = type;
+
+ st_api_make_current(osmesa->st, &osbuffer->base, &osbuffer->base);
+
+ /* XXX: We should probably load the current color value into the buffer here
+ * to match classic swrast behavior (context's fb starts with the contents of
+ * your pixel buffer).
+ */
+
+ if (!osmesa->ever_used) {
+ /* one-time init, just postprocessing for now */
+ bool any_pp_enabled = false;
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) {
+ if (osmesa->pp_enabled[i]) {
+ any_pp_enabled = true;
+ break;
+ }
+ }
+
+ if (any_pp_enabled) {
+ osmesa->pp = pp_init(osmesa->st->pipe,
+ osmesa->pp_enabled,
+ osmesa->st->cso_context,
+ osmesa->st,
+ st_context_invalidate_state);
+
+ pp_init_fbos(osmesa->pp, width, height);
+ }
+
+ osmesa->ever_used = true;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaGetCurrentContext(void)
+{
+ struct st_context *st = st_api_get_current();
+ return st ? (OSMesaContext) st->frontend_context : NULL;
+}
+
+
+
+GLAPI void GLAPIENTRY
+OSMesaPixelStore(GLint pname, GLint value)
+{
+ OSMesaContext osmesa = OSMesaGetCurrentContext();
+
+ switch (pname) {
+ case OSMESA_ROW_LENGTH:
+ osmesa->user_row_length = value;
+ break;
+ case OSMESA_Y_UP:
+ osmesa->y_up = value ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n");
+ return;
+ }
+}
+
+
+GLAPI void GLAPIENTRY
+OSMesaGetIntegerv(GLint pname, GLint *value)
+{
+ OSMesaContext osmesa = OSMesaGetCurrentContext();
+ struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL;
+
+ switch (pname) {
+ case OSMESA_WIDTH:
+ *value = osbuffer ? osbuffer->width : 0;
+ return;
+ case OSMESA_HEIGHT:
+ *value = osbuffer ? osbuffer->height : 0;
+ return;
+ case OSMESA_FORMAT:
+ *value = osmesa->format;
+ return;
+ case OSMESA_TYPE:
+ /* current color buffer's data type */
+ *value = osmesa->type;
+ return;
+ case OSMESA_ROW_LENGTH:
+ *value = osmesa->user_row_length;
+ return;
+ case OSMESA_Y_UP:
+ *value = osmesa->y_up;
+ return;
+ case OSMESA_MAX_WIDTH:
+ FALLTHROUGH;
+ case OSMESA_MAX_HEIGHT:
+ {
+ struct pipe_screen *screen = get_st_manager()->screen;
+ *value = screen->caps.max_texture_2d_size;
+ }
+ return;
+ default:
+ fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n");
+ return;
+ }
+}
+
+
+/**
+ * Return information about the depth buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * bytesPerValue - bytes per depth value (2 or 4)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLAPI GLboolean GLAPIENTRY
+OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height,
+ GLint *bytesPerValue, void **buffer)
+{
+ struct osmesa_buffer *osbuffer = c->current_buffer;
+ struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL];
+
+ if (!res) {
+ *width = 0;
+ *height = 0;
+ *bytesPerValue = 0;
+ *buffer = NULL;
+ return GL_FALSE;
+ }
+
+ *width = res->width0;
+ *height = res->height0;
+ *bytesPerValue = util_format_get_blocksize(res->format);
+
+ if (!c->zs) {
+ c->zs_stride = *width * *bytesPerValue;
+ c->zs = calloc(c->zs_stride, *height);
+ if (!c->zs)
+ return GL_FALSE;
+
+ osmesa_read_buffer(c, res, c->zs, c->zs_stride, true);
+ }
+
+ *buffer = c->zs;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Return the color buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * format - the pixel format (OSMESA_FORMAT)
+ * buffer - pointer to color buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLAPI GLboolean GLAPIENTRY
+OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width,
+ GLint *height, GLint *format, void **buffer)
+{
+ struct osmesa_buffer *osbuffer = osmesa->current_buffer;
+
+ if (osbuffer) {
+ *width = osbuffer->width;
+ *height = osbuffer->height;
+ *format = osmesa->format;
+ *buffer = osbuffer->map;
+ return GL_TRUE;
+ }
+ else {
+ *width = 0;
+ *height = 0;
+ *format = 0;
+ *buffer = 0;
+ return GL_FALSE;
+ }
+}
+
+
+struct name_function
+{
+ const char *Name;
+ OSMESAproc Function;
+};
+
+static struct name_function functions[] = {
+ { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
+ { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
+ { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs },
+ { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
+ { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
+ { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
+ { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore },
+ { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
+ { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
+ { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
+ { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
+ { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
+ { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess },
+ { NULL, NULL }
+};
+
+
+GLAPI OSMESAproc GLAPIENTRY
+OSMesaGetProcAddress(const char *funcName)
+{
+ int i;
+ for (i = 0; functions[i].Name; i++) {
+ if (strcmp(functions[i].Name, funcName) == 0)
+ return functions[i].Function;
+ }
+ return _mesa_glapi_get_proc_address(funcName);
+}
+
+
+GLAPI void GLAPIENTRY
+OSMesaColorClamp(GLboolean enable)
+{
+ extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp);
+
+ _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
+ enable ? GL_TRUE : GL_FIXED_ONLY_ARB);
+}
+
+
+GLAPI void GLAPIENTRY
+OSMesaPostprocess(OSMesaContext osmesa, const char *filter,
+ unsigned enable_value)
+{
+ if (!osmesa->ever_used) {
+ /* We can only enable/disable postprocess filters before a context
+ * is made current for the first time.
+ */
+ unsigned i;
+
+ for (i = 0; i < PP_FILTERS; i++) {
+ if (strcmp(pp_filters[i].name, filter) == 0) {
+ osmesa->pp_enabled[i] = enable_value;
+ return;
+ }
+ }
+ debug_warning("OSMesaPostprocess(unknown filter)\n");
+ }
+ else {
+ debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n");
+ }
+}
diff -ruN mesa-26.1.4/src/gallium/meson.build mesa-26.1.4-banan_os/src/gallium/meson.build
--- mesa-26.1.4/src/gallium/meson.build 2026-07-01 17:16:13.000000000 +0300
+++ mesa-26.1.4-banan_os/src/gallium/meson.build 2026-07-05 04:20:14.035181849 +0300
@@ -232,6 +232,10 @@
subdir('frontends/dri')
subdir('targets/dri')
endif
+if with_osmesa
+ subdir('frontends/osmesa')
+ subdir('targets/osmesa')
+endif
if with_platform_haiku
subdir('frontends/hgl')
endif
diff -ruN mesa-26.1.4/src/gallium/targets/osmesa/meson.build mesa-26.1.4-banan_os/src/gallium/targets/osmesa/meson.build
--- mesa-26.1.4/src/gallium/targets/osmesa/meson.build 1970-01-01 02:00:00.000000000 +0200
+++ mesa-26.1.4-banan_os/src/gallium/targets/osmesa/meson.build 2026-07-05 04:20:14.212936332 +0300
@@ -0,0 +1,36 @@
+# Copyright © 2017 Intel Corporation
+# SPDX-License-Identifier: MIT
+
+osmesa_link_args = []
+osmesa_link_deps = []
+
+if with_ld_version_script
+ osmesa_link_args += ['-Wl,--version-script', join_paths(meson.current_source_dir(), 'osmesa.sym')]
+ osmesa_link_deps += files('osmesa.sym')
+endif
+
+libosmesa = shared_library(
+ osmesa_lib_name,
+ files('osmesa_target.c'),
+ include_directories : [
+ inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_gallium_winsys,
+ inc_gallium_drivers,
+ ],
+ gnu_symbol_visibility : 'hidden',
+ link_args : [ld_args_gc_sections, osmesa_link_args],
+ link_depends : osmesa_link_deps,
+ link_whole : [libosmesa_st, libglapi_bridge],
+ link_with : [libmesa, libgallium, libglapi, libws_null],
+ dependencies : [dep_ws2_32, dep_thread, dep_clock, dep_unwind, driver_swrast, idep_mesautil],
+ install : true,
+ version : '8.0.0',
+ darwin_versions : '9.0.0',
+)
+
+pkg.generate(
+ name : 'osmesa',
+ description : 'Mesa Off-screen Rendering Library',
+ version : '8.0.0',
+ libraries : libosmesa,
+ libraries_private : gl_priv_libs,
+)
diff -ruN mesa-26.1.4/src/gallium/targets/osmesa/osmesa.sym mesa-26.1.4-banan_os/src/gallium/targets/osmesa/osmesa.sym
--- mesa-26.1.4/src/gallium/targets/osmesa/osmesa.sym 1970-01-01 02:00:00.000000000 +0200
+++ mesa-26.1.4-banan_os/src/gallium/targets/osmesa/osmesa.sym 2026-07-05 04:20:14.212992485 +0300
@@ -0,0 +1,19 @@
+{
+ global:
+ OSMesaColorClamp;
+ OSMesaCreateContext;
+ OSMesaCreateContextAttribs;
+ OSMesaCreateContextExt;
+ OSMesaDestroyContext;
+ OSMesaGetColorBuffer;
+ OSMesaGetCurrentContext;
+ OSMesaGetDepthBuffer;
+ OSMesaGetIntegerv;
+ OSMesaGetProcAddress;
+ OSMesaMakeCurrent;
+ OSMesaPixelStore;
+ OSMesaPostprocess;
+ gl*;
+ local:
+ *;
+};
diff -ruN mesa-26.1.4/src/gallium/targets/osmesa/osmesa_target.c mesa-26.1.4-banan_os/src/gallium/targets/osmesa/osmesa_target.c
--- mesa-26.1.4/src/gallium/targets/osmesa/osmesa_target.c 1970-01-01 02:00:00.000000000 +0200
+++ mesa-26.1.4-banan_os/src/gallium/targets/osmesa/osmesa_target.c 2026-07-05 04:20:14.213049196 +0300
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "target-helpers/inline_sw_helper.h"
+#include "target-helpers/inline_debug_helper.h"
+
+#include "sw/null/null_sw_winsys.h"
+
+
+struct pipe_screen *
+osmesa_create_screen(void);
+
+
+struct pipe_screen *
+osmesa_create_screen(void)
+{
+ struct sw_winsys *winsys;
+ struct pipe_screen *screen;
+
+ /* We use a null software winsys since we always just render to ordinary
+ * driver resources.
+ */
+ winsys = null_sw_create();
+ if (!winsys)
+ return NULL;
+
+ /* Create llvmpipe or softpipe screen */
+ screen = sw_screen_create(winsys);
+ if (!screen) {
+ winsys->destroy(winsys);
+ return NULL;
+ }
+
+ /* Inject optional trace, debug, etc. wrappers */
+ return debug_screen_wrap(screen);
+}