xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/osmesa/osmesa.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (c) 2013  Brian Paul   All Rights Reserved.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
12*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
21*61046927SAndroid Build Coastguard Worker  */
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker /*
25*61046927SAndroid Build Coastguard Worker  * Off-Screen rendering into client memory.
26*61046927SAndroid Build Coastguard Worker  * OpenGL gallium frontend for softpipe and llvmpipe.
27*61046927SAndroid Build Coastguard Worker  *
28*61046927SAndroid Build Coastguard Worker  * Notes:
29*61046927SAndroid Build Coastguard Worker  *
30*61046927SAndroid Build Coastguard Worker  * If Gallium is built with LLVM support we use the llvmpipe driver.
31*61046927SAndroid Build Coastguard Worker  * Otherwise we use softpipe.  The GALLIUM_DRIVER environment variable
32*61046927SAndroid Build Coastguard Worker  * may be set to "softpipe" or "llvmpipe" to override.
33*61046927SAndroid Build Coastguard Worker  *
34*61046927SAndroid Build Coastguard Worker  * With softpipe we could render directly into the user's buffer by using a
35*61046927SAndroid Build Coastguard Worker  * display target resource.  However, softpipe doesn't support "upside-down"
36*61046927SAndroid Build Coastguard Worker  * rendering which would be needed for the OSMESA_Y_UP=TRUE case.
37*61046927SAndroid Build Coastguard Worker  *
38*61046927SAndroid Build Coastguard Worker  * With llvmpipe we could only render directly into the user's buffer when its
39*61046927SAndroid Build Coastguard Worker  * width and height is a multiple of the tile size (64 pixels).
40*61046927SAndroid Build Coastguard Worker  *
41*61046927SAndroid Build Coastguard Worker  * Because of these constraints we always render into ordinary resources then
42*61046927SAndroid Build Coastguard Worker  * copy the results to the user's buffer in the flush_front() function which
43*61046927SAndroid Build Coastguard Worker  * is called when the app calls glFlush/Finish.
44*61046927SAndroid Build Coastguard Worker  *
45*61046927SAndroid Build Coastguard Worker  * In general, the OSMesa interface is pretty ugly and not a good match
46*61046927SAndroid Build Coastguard Worker  * for Gallium.  But we're interested in doing the best we can to preserve
47*61046927SAndroid Build Coastguard Worker  * application portability.  With a little work we could come up with a
48*61046927SAndroid Build Coastguard Worker  * much nicer, new off-screen Gallium interface...
49*61046927SAndroid Build Coastguard Worker  */
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker /**
52*61046927SAndroid Build Coastguard Worker  * The following block is for avoid windows.h to be included
53*61046927SAndroid Build Coastguard Worker  * and osmesa require APIENTRY to be defined
54*61046927SAndroid Build Coastguard Worker  */
55*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
56*61046927SAndroid Build Coastguard Worker #ifndef APIENTRY
57*61046927SAndroid Build Coastguard Worker #define APIENTRY GLAPIENTRY
58*61046927SAndroid Build Coastguard Worker #endif
59*61046927SAndroid Build Coastguard Worker #include "GL/osmesa.h"
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker #include <stdio.h>
62*61046927SAndroid Build Coastguard Worker #include <c11/threads.h>
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_context.h"
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker #include "glapi/glapi.h"  /* for OSMesaGetProcAddress below */
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker #include "pipe/p_context.h"
69*61046927SAndroid Build Coastguard Worker #include "pipe/p_screen.h"
70*61046927SAndroid Build Coastguard Worker #include "pipe/p_state.h"
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
73*61046927SAndroid Build Coastguard Worker #include "util/box.h"
74*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
75*61046927SAndroid Build Coastguard Worker #include "util/format/u_format.h"
76*61046927SAndroid Build Coastguard Worker #include "util/u_inlines.h"
77*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker #include "postprocess/filters.h"
80*61046927SAndroid Build Coastguard Worker #include "postprocess/postprocess.h"
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker #include "frontend/api.h"
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker extern struct pipe_screen *
87*61046927SAndroid Build Coastguard Worker osmesa_create_screen(void);
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker struct osmesa_buffer
92*61046927SAndroid Build Coastguard Worker {
93*61046927SAndroid Build Coastguard Worker    struct pipe_frontend_drawable base;
94*61046927SAndroid Build Coastguard Worker    struct st_visual visual;
95*61046927SAndroid Build Coastguard Worker    unsigned width, height;
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    void *map;
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *next;  /**< next in linked list */
102*61046927SAndroid Build Coastguard Worker };
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker struct osmesa_context
106*61046927SAndroid Build Coastguard Worker {
107*61046927SAndroid Build Coastguard Worker    struct st_context *st;
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker    bool ever_used;     /*< Has this context ever been current? */
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *current_buffer;
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    /* Storage for depth/stencil, if the user has requested access.  The backing
114*61046927SAndroid Build Coastguard Worker     * driver always has its own storage for the actual depth/stencil, which we
115*61046927SAndroid Build Coastguard Worker     * have to transfer in and out.
116*61046927SAndroid Build Coastguard Worker     */
117*61046927SAndroid Build Coastguard Worker    void *zs;
118*61046927SAndroid Build Coastguard Worker    unsigned zs_stride;
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker    enum pipe_format depth_stencil_format, accum_format;
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    GLenum format;         /*< User-specified context format */
123*61046927SAndroid Build Coastguard Worker    GLenum type;           /*< Buffer's data type */
124*61046927SAndroid Build Coastguard Worker    GLint user_row_length; /*< user-specified number of pixels per row */
125*61046927SAndroid Build Coastguard Worker    GLboolean y_up;        /*< TRUE  -> Y increases upward */
126*61046927SAndroid Build Coastguard Worker                           /*< FALSE -> Y increases downward */
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    /** Which postprocessing filters are enabled. */
129*61046927SAndroid Build Coastguard Worker    unsigned pp_enabled[PP_FILTERS];
130*61046927SAndroid Build Coastguard Worker    struct pp_queue_t *pp;
131*61046927SAndroid Build Coastguard Worker };
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker /**
134*61046927SAndroid Build Coastguard Worker  * Called from the ST manager.
135*61046927SAndroid Build Coastguard Worker  */
136*61046927SAndroid Build Coastguard Worker static int
osmesa_st_get_param(struct pipe_frontend_screen * fscreen,enum st_manager_param param)137*61046927SAndroid Build Coastguard Worker osmesa_st_get_param(struct pipe_frontend_screen *fscreen, enum st_manager_param param)
138*61046927SAndroid Build Coastguard Worker {
139*61046927SAndroid Build Coastguard Worker    /* no-op */
140*61046927SAndroid Build Coastguard Worker    return 0;
141*61046927SAndroid Build Coastguard Worker }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker static struct pipe_frontend_screen *global_fscreen = NULL;
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker static void
destroy_st_manager(void)146*61046927SAndroid Build Coastguard Worker destroy_st_manager(void)
147*61046927SAndroid Build Coastguard Worker {
148*61046927SAndroid Build Coastguard Worker    if (global_fscreen) {
149*61046927SAndroid Build Coastguard Worker       if (global_fscreen->screen)
150*61046927SAndroid Build Coastguard Worker          global_fscreen->screen->destroy(global_fscreen->screen);
151*61046927SAndroid Build Coastguard Worker       FREE(global_fscreen);
152*61046927SAndroid Build Coastguard Worker    }
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker static void
create_st_manager(void)156*61046927SAndroid Build Coastguard Worker create_st_manager(void)
157*61046927SAndroid Build Coastguard Worker {
158*61046927SAndroid Build Coastguard Worker    if (atexit(destroy_st_manager) != 0)
159*61046927SAndroid Build Coastguard Worker       return;
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    global_fscreen = CALLOC_STRUCT(pipe_frontend_screen);
162*61046927SAndroid Build Coastguard Worker    if (global_fscreen) {
163*61046927SAndroid Build Coastguard Worker       global_fscreen->screen = osmesa_create_screen();
164*61046927SAndroid Build Coastguard Worker       global_fscreen->get_param = osmesa_st_get_param;
165*61046927SAndroid Build Coastguard Worker       global_fscreen->get_egl_image = NULL;
166*61046927SAndroid Build Coastguard Worker    }
167*61046927SAndroid Build Coastguard Worker }
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker /**
170*61046927SAndroid Build Coastguard Worker  * Create/return a singleton st_manager object.
171*61046927SAndroid Build Coastguard Worker  */
172*61046927SAndroid Build Coastguard Worker static struct pipe_frontend_screen *
get_st_manager(void)173*61046927SAndroid Build Coastguard Worker get_st_manager(void)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker    static once_flag create_once_flag = ONCE_FLAG_INIT;
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    call_once(&create_once_flag, create_st_manager);
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker    return global_fscreen;
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker /* Reads the color or depth buffer from the backing context to either the user storage
183*61046927SAndroid Build Coastguard Worker  * (color buffer) or our temporary (z/s)
184*61046927SAndroid Build Coastguard Worker  */
185*61046927SAndroid Build Coastguard Worker static void
osmesa_read_buffer(OSMesaContext osmesa,struct pipe_resource * res,void * dst,int dst_stride,bool y_up)186*61046927SAndroid Build Coastguard Worker osmesa_read_buffer(OSMesaContext osmesa, struct pipe_resource *res, void *dst,
187*61046927SAndroid Build Coastguard Worker                    int dst_stride, bool y_up)
188*61046927SAndroid Build Coastguard Worker {
189*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = osmesa->st->pipe;
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker    struct pipe_box box;
192*61046927SAndroid Build Coastguard Worker    u_box_2d(0, 0, res->width0, res->height0, &box);
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    struct pipe_transfer *transfer = NULL;
195*61046927SAndroid Build Coastguard Worker    uint8_t *src = pipe->texture_map(pipe, res, 0, PIPE_MAP_READ, &box,
196*61046927SAndroid Build Coastguard Worker                                    &transfer);
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    /*
199*61046927SAndroid Build Coastguard Worker     * Copy the color buffer from the resource to the user's buffer.
200*61046927SAndroid Build Coastguard Worker     */
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker    if (y_up) {
203*61046927SAndroid Build Coastguard Worker       /* need to flip image upside down */
204*61046927SAndroid Build Coastguard Worker       dst = (uint8_t *)dst + (res->height0 - 1) * dst_stride;
205*61046927SAndroid Build Coastguard Worker       dst_stride = -dst_stride;
206*61046927SAndroid Build Coastguard Worker    }
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker    unsigned bpp = util_format_get_blocksize(res->format);
209*61046927SAndroid Build Coastguard Worker    for (unsigned y = 0; y < res->height0; y++)
210*61046927SAndroid Build Coastguard Worker    {
211*61046927SAndroid Build Coastguard Worker       memcpy(dst, src, bpp * res->width0);
212*61046927SAndroid Build Coastguard Worker       dst = (uint8_t *)dst + dst_stride;
213*61046927SAndroid Build Coastguard Worker       src += transfer->stride;
214*61046927SAndroid Build Coastguard Worker    }
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    pipe->texture_unmap(pipe, transfer);
217*61046927SAndroid Build Coastguard Worker }
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker /**
221*61046927SAndroid Build Coastguard Worker  * Given an OSMESA_x format and a GL_y type, return the best
222*61046927SAndroid Build Coastguard Worker  * matching PIPE_FORMAT_z.
223*61046927SAndroid Build Coastguard Worker  * Note that we can't exactly match all user format/type combinations
224*61046927SAndroid Build Coastguard Worker  * with gallium formats.  If we find this to be a problem, we can
225*61046927SAndroid Build Coastguard Worker  * implement more elaborate format/type conversion in the flush_front()
226*61046927SAndroid Build Coastguard Worker  * function.
227*61046927SAndroid Build Coastguard Worker  */
228*61046927SAndroid Build Coastguard Worker static enum pipe_format
osmesa_choose_format(GLenum format,GLenum type)229*61046927SAndroid Build Coastguard Worker osmesa_choose_format(GLenum format, GLenum type)
230*61046927SAndroid Build Coastguard Worker {
231*61046927SAndroid Build Coastguard Worker    switch (format) {
232*61046927SAndroid Build Coastguard Worker    case OSMESA_RGBA:
233*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_BYTE) {
234*61046927SAndroid Build Coastguard Worker #if UTIL_ARCH_LITTLE_ENDIAN
235*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R8G8B8A8_UNORM;
236*61046927SAndroid Build Coastguard Worker #else
237*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_A8B8G8R8_UNORM;
238*61046927SAndroid Build Coastguard Worker #endif
239*61046927SAndroid Build Coastguard Worker       }
240*61046927SAndroid Build Coastguard Worker       else if (type == GL_UNSIGNED_SHORT) {
241*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R16G16B16A16_UNORM;
242*61046927SAndroid Build Coastguard Worker       }
243*61046927SAndroid Build Coastguard Worker       else if (type == GL_FLOAT) {
244*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R32G32B32A32_FLOAT;
245*61046927SAndroid Build Coastguard Worker       }
246*61046927SAndroid Build Coastguard Worker       else {
247*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_NONE;
248*61046927SAndroid Build Coastguard Worker       }
249*61046927SAndroid Build Coastguard Worker       break;
250*61046927SAndroid Build Coastguard Worker    case OSMESA_BGRA:
251*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_BYTE) {
252*61046927SAndroid Build Coastguard Worker #if UTIL_ARCH_LITTLE_ENDIAN
253*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_B8G8R8A8_UNORM;
254*61046927SAndroid Build Coastguard Worker #else
255*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_A8R8G8B8_UNORM;
256*61046927SAndroid Build Coastguard Worker #endif
257*61046927SAndroid Build Coastguard Worker       }
258*61046927SAndroid Build Coastguard Worker       else if (type == GL_UNSIGNED_SHORT) {
259*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R16G16B16A16_UNORM;
260*61046927SAndroid Build Coastguard Worker       }
261*61046927SAndroid Build Coastguard Worker       else if (type == GL_FLOAT) {
262*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R32G32B32A32_FLOAT;
263*61046927SAndroid Build Coastguard Worker       }
264*61046927SAndroid Build Coastguard Worker       else {
265*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_NONE;
266*61046927SAndroid Build Coastguard Worker       }
267*61046927SAndroid Build Coastguard Worker       break;
268*61046927SAndroid Build Coastguard Worker    case OSMESA_ARGB:
269*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_BYTE) {
270*61046927SAndroid Build Coastguard Worker #if UTIL_ARCH_LITTLE_ENDIAN
271*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_A8R8G8B8_UNORM;
272*61046927SAndroid Build Coastguard Worker #else
273*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_B8G8R8A8_UNORM;
274*61046927SAndroid Build Coastguard Worker #endif
275*61046927SAndroid Build Coastguard Worker       }
276*61046927SAndroid Build Coastguard Worker       else if (type == GL_UNSIGNED_SHORT) {
277*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R16G16B16A16_UNORM;
278*61046927SAndroid Build Coastguard Worker       }
279*61046927SAndroid Build Coastguard Worker       else if (type == GL_FLOAT) {
280*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R32G32B32A32_FLOAT;
281*61046927SAndroid Build Coastguard Worker       }
282*61046927SAndroid Build Coastguard Worker       else {
283*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_NONE;
284*61046927SAndroid Build Coastguard Worker       }
285*61046927SAndroid Build Coastguard Worker       break;
286*61046927SAndroid Build Coastguard Worker    case OSMESA_RGB:
287*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_BYTE) {
288*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R8G8B8_UNORM;
289*61046927SAndroid Build Coastguard Worker       }
290*61046927SAndroid Build Coastguard Worker       else if (type == GL_UNSIGNED_SHORT) {
291*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R16G16B16_UNORM;
292*61046927SAndroid Build Coastguard Worker       }
293*61046927SAndroid Build Coastguard Worker       else if (type == GL_FLOAT) {
294*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_R32G32B32_FLOAT;
295*61046927SAndroid Build Coastguard Worker       }
296*61046927SAndroid Build Coastguard Worker       else {
297*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_NONE;
298*61046927SAndroid Build Coastguard Worker       }
299*61046927SAndroid Build Coastguard Worker       break;
300*61046927SAndroid Build Coastguard Worker    case OSMESA_BGR:
301*61046927SAndroid Build Coastguard Worker       /* No gallium format for this one */
302*61046927SAndroid Build Coastguard Worker       return PIPE_FORMAT_NONE;
303*61046927SAndroid Build Coastguard Worker    case OSMESA_RGB_565:
304*61046927SAndroid Build Coastguard Worker       if (type != GL_UNSIGNED_SHORT_5_6_5)
305*61046927SAndroid Build Coastguard Worker          return PIPE_FORMAT_NONE;
306*61046927SAndroid Build Coastguard Worker       return PIPE_FORMAT_B5G6R5_UNORM;
307*61046927SAndroid Build Coastguard Worker    default:
308*61046927SAndroid Build Coastguard Worker       return PIPE_FORMAT_NONE;
309*61046927SAndroid Build Coastguard Worker    }
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker /**
314*61046927SAndroid Build Coastguard Worker  * Initialize an st_visual object.
315*61046927SAndroid Build Coastguard Worker  */
316*61046927SAndroid Build Coastguard Worker 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)317*61046927SAndroid Build Coastguard Worker osmesa_init_st_visual(struct st_visual *vis,
318*61046927SAndroid Build Coastguard Worker                       enum pipe_format color_format,
319*61046927SAndroid Build Coastguard Worker                       enum pipe_format ds_format,
320*61046927SAndroid Build Coastguard Worker                       enum pipe_format accum_format)
321*61046927SAndroid Build Coastguard Worker {
322*61046927SAndroid Build Coastguard Worker    vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker    if (ds_format != PIPE_FORMAT_NONE)
325*61046927SAndroid Build Coastguard Worker       vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
326*61046927SAndroid Build Coastguard Worker    if (accum_format != PIPE_FORMAT_NONE)
327*61046927SAndroid Build Coastguard Worker       vis->buffer_mask |= ST_ATTACHMENT_ACCUM;
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker    vis->color_format = color_format;
330*61046927SAndroid Build Coastguard Worker    vis->depth_stencil_format = ds_format;
331*61046927SAndroid Build Coastguard Worker    vis->accum_format = accum_format;
332*61046927SAndroid Build Coastguard Worker    vis->samples = 1;
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker /**
337*61046927SAndroid Build Coastguard Worker  * Return the osmesa_buffer that corresponds to an pipe_frontend_drawable.
338*61046927SAndroid Build Coastguard Worker  */
339*61046927SAndroid Build Coastguard Worker static inline struct osmesa_buffer *
drawable_to_osbuffer(struct pipe_frontend_drawable * drawable)340*61046927SAndroid Build Coastguard Worker drawable_to_osbuffer(struct pipe_frontend_drawable *drawable)
341*61046927SAndroid Build Coastguard Worker {
342*61046927SAndroid Build Coastguard Worker    return (struct osmesa_buffer *)drawable;
343*61046927SAndroid Build Coastguard Worker }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker /**
347*61046927SAndroid Build Coastguard Worker  * Called via glFlush/glFinish.  This is where we copy the contents
348*61046927SAndroid Build Coastguard Worker  * of the driver's color buffer into the user-specified buffer.
349*61046927SAndroid Build Coastguard Worker  */
350*61046927SAndroid Build Coastguard Worker static bool
osmesa_st_framebuffer_flush_front(struct st_context * st,struct pipe_frontend_drawable * drawable,enum st_attachment_type statt)351*61046927SAndroid Build Coastguard Worker osmesa_st_framebuffer_flush_front(struct st_context *st,
352*61046927SAndroid Build Coastguard Worker                                   struct pipe_frontend_drawable *drawable,
353*61046927SAndroid Build Coastguard Worker                                   enum st_attachment_type statt)
354*61046927SAndroid Build Coastguard Worker {
355*61046927SAndroid Build Coastguard Worker    OSMesaContext osmesa = OSMesaGetCurrentContext();
356*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = drawable_to_osbuffer(drawable);
357*61046927SAndroid Build Coastguard Worker    struct pipe_resource *res = osbuffer->textures[statt];
358*61046927SAndroid Build Coastguard Worker    unsigned bpp;
359*61046927SAndroid Build Coastguard Worker    int dst_stride;
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    if (statt != ST_ATTACHMENT_FRONT_LEFT)
362*61046927SAndroid Build Coastguard Worker       return false;
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker    if (osmesa->pp) {
365*61046927SAndroid Build Coastguard Worker       struct pipe_resource *zsbuf = NULL;
366*61046927SAndroid Build Coastguard Worker       unsigned i;
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker       /* Find the z/stencil buffer if there is one */
369*61046927SAndroid Build Coastguard Worker       for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) {
370*61046927SAndroid Build Coastguard Worker          struct pipe_resource *res = osbuffer->textures[i];
371*61046927SAndroid Build Coastguard Worker          if (res) {
372*61046927SAndroid Build Coastguard Worker             const struct util_format_description *desc =
373*61046927SAndroid Build Coastguard Worker                util_format_description(res->format);
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker             if (util_format_has_depth(desc)) {
376*61046927SAndroid Build Coastguard Worker                zsbuf = res;
377*61046927SAndroid Build Coastguard Worker                break;
378*61046927SAndroid Build Coastguard Worker             }
379*61046927SAndroid Build Coastguard Worker          }
380*61046927SAndroid Build Coastguard Worker       }
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker       /* run the postprocess stage(s) */
383*61046927SAndroid Build Coastguard Worker       pp_run(osmesa->pp, res, res, zsbuf);
384*61046927SAndroid Build Coastguard Worker    }
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    /* Snapshot the color buffer to the user's buffer. */
387*61046927SAndroid Build Coastguard Worker    bpp = util_format_get_blocksize(osbuffer->visual.color_format);
388*61046927SAndroid Build Coastguard Worker    if (osmesa->user_row_length)
389*61046927SAndroid Build Coastguard Worker       dst_stride = bpp * osmesa->user_row_length;
390*61046927SAndroid Build Coastguard Worker    else
391*61046927SAndroid Build Coastguard Worker       dst_stride = bpp * osbuffer->width;
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker    osmesa_read_buffer(osmesa, res, osbuffer->map, dst_stride, osmesa->y_up);
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    /* If the user has requested the Z/S buffer, then snapshot that one too. */
396*61046927SAndroid Build Coastguard Worker    if (osmesa->zs) {
397*61046927SAndroid Build Coastguard Worker       osmesa_read_buffer(osmesa, osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL],
398*61046927SAndroid Build Coastguard Worker                          osmesa->zs, osmesa->zs_stride, true);
399*61046927SAndroid Build Coastguard Worker    }
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker    return true;
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker /**
406*61046927SAndroid Build Coastguard Worker  * Called by the st manager to validate the framebuffer (allocate
407*61046927SAndroid Build Coastguard Worker  * its resources).
408*61046927SAndroid Build Coastguard Worker  */
409*61046927SAndroid Build Coastguard Worker 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)410*61046927SAndroid Build Coastguard Worker osmesa_st_framebuffer_validate(struct st_context *st,
411*61046927SAndroid Build Coastguard Worker                                struct pipe_frontend_drawable *drawable,
412*61046927SAndroid Build Coastguard Worker                                const enum st_attachment_type *statts,
413*61046927SAndroid Build Coastguard Worker                                unsigned count,
414*61046927SAndroid Build Coastguard Worker                                struct pipe_resource **out,
415*61046927SAndroid Build Coastguard Worker                                struct pipe_resource **resolve)
416*61046927SAndroid Build Coastguard Worker {
417*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen = get_st_manager()->screen;
418*61046927SAndroid Build Coastguard Worker    enum st_attachment_type i;
419*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = drawable_to_osbuffer(drawable);
420*61046927SAndroid Build Coastguard Worker    struct pipe_resource templat;
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker    memset(&templat, 0, sizeof(templat));
423*61046927SAndroid Build Coastguard Worker    templat.target = PIPE_TEXTURE_RECT;
424*61046927SAndroid Build Coastguard Worker    templat.format = 0; /* setup below */
425*61046927SAndroid Build Coastguard Worker    templat.last_level = 0;
426*61046927SAndroid Build Coastguard Worker    templat.width0 = osbuffer->width;
427*61046927SAndroid Build Coastguard Worker    templat.height0 = osbuffer->height;
428*61046927SAndroid Build Coastguard Worker    templat.depth0 = 1;
429*61046927SAndroid Build Coastguard Worker    templat.array_size = 1;
430*61046927SAndroid Build Coastguard Worker    templat.usage = PIPE_USAGE_DEFAULT;
431*61046927SAndroid Build Coastguard Worker    templat.bind = 0; /* setup below */
432*61046927SAndroid Build Coastguard Worker    templat.flags = 0;
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker    for (i = 0; i < count; i++) {
435*61046927SAndroid Build Coastguard Worker       enum pipe_format format = PIPE_FORMAT_NONE;
436*61046927SAndroid Build Coastguard Worker       unsigned bind = 0;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker       /*
439*61046927SAndroid Build Coastguard Worker        * At this time, we really only need to handle the front-left color
440*61046927SAndroid Build Coastguard Worker        * attachment, since that's all we specified for the visual in
441*61046927SAndroid Build Coastguard Worker        * osmesa_init_st_visual().
442*61046927SAndroid Build Coastguard Worker        */
443*61046927SAndroid Build Coastguard Worker       if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
444*61046927SAndroid Build Coastguard Worker          format = osbuffer->visual.color_format;
445*61046927SAndroid Build Coastguard Worker          bind = PIPE_BIND_RENDER_TARGET;
446*61046927SAndroid Build Coastguard Worker       }
447*61046927SAndroid Build Coastguard Worker       else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
448*61046927SAndroid Build Coastguard Worker          format = osbuffer->visual.depth_stencil_format;
449*61046927SAndroid Build Coastguard Worker          bind = PIPE_BIND_DEPTH_STENCIL;
450*61046927SAndroid Build Coastguard Worker       }
451*61046927SAndroid Build Coastguard Worker       else if (statts[i] == ST_ATTACHMENT_ACCUM) {
452*61046927SAndroid Build Coastguard Worker          format = osbuffer->visual.accum_format;
453*61046927SAndroid Build Coastguard Worker          bind = PIPE_BIND_RENDER_TARGET;
454*61046927SAndroid Build Coastguard Worker       }
455*61046927SAndroid Build Coastguard Worker       else {
456*61046927SAndroid Build Coastguard Worker          debug_warning("Unexpected attachment type in "
457*61046927SAndroid Build Coastguard Worker                        "osmesa_st_framebuffer_validate()");
458*61046927SAndroid Build Coastguard Worker       }
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker       templat.format = format;
461*61046927SAndroid Build Coastguard Worker       templat.bind = bind;
462*61046927SAndroid Build Coastguard Worker       pipe_resource_reference(&out[i], NULL);
463*61046927SAndroid Build Coastguard Worker       out[i] = osbuffer->textures[statts[i]] =
464*61046927SAndroid Build Coastguard Worker          screen->resource_create(screen, &templat);
465*61046927SAndroid Build Coastguard Worker    }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    return true;
468*61046927SAndroid Build Coastguard Worker }
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker static uint32_t osmesa_fb_ID = 0;
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker /**
474*61046927SAndroid Build Coastguard Worker  * Create new buffer and add to linked list.
475*61046927SAndroid Build Coastguard Worker  */
476*61046927SAndroid Build Coastguard Worker static struct osmesa_buffer *
osmesa_create_buffer(enum pipe_format color_format,enum pipe_format ds_format,enum pipe_format accum_format)477*61046927SAndroid Build Coastguard Worker osmesa_create_buffer(enum pipe_format color_format,
478*61046927SAndroid Build Coastguard Worker                      enum pipe_format ds_format,
479*61046927SAndroid Build Coastguard Worker                      enum pipe_format accum_format)
480*61046927SAndroid Build Coastguard Worker {
481*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer);
482*61046927SAndroid Build Coastguard Worker    if (osbuffer) {
483*61046927SAndroid Build Coastguard Worker       osbuffer->base.flush_front = osmesa_st_framebuffer_flush_front;
484*61046927SAndroid Build Coastguard Worker       osbuffer->base.validate = osmesa_st_framebuffer_validate;
485*61046927SAndroid Build Coastguard Worker       p_atomic_set(&osbuffer->base.stamp, 1);
486*61046927SAndroid Build Coastguard Worker       osbuffer->base.ID = p_atomic_inc_return(&osmesa_fb_ID);
487*61046927SAndroid Build Coastguard Worker       osbuffer->base.fscreen = get_st_manager();
488*61046927SAndroid Build Coastguard Worker       osbuffer->base.visual = &osbuffer->visual;
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker       osmesa_init_st_visual(&osbuffer->visual, color_format,
491*61046927SAndroid Build Coastguard Worker                             ds_format, accum_format);
492*61046927SAndroid Build Coastguard Worker    }
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker    return osbuffer;
495*61046927SAndroid Build Coastguard Worker }
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker static void
osmesa_destroy_buffer(struct osmesa_buffer * osbuffer)499*61046927SAndroid Build Coastguard Worker osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
500*61046927SAndroid Build Coastguard Worker {
501*61046927SAndroid Build Coastguard Worker    /*
502*61046927SAndroid Build Coastguard Worker     * Notify the state manager that the associated framebuffer interface
503*61046927SAndroid Build Coastguard Worker     * is no longer valid.
504*61046927SAndroid Build Coastguard Worker     */
505*61046927SAndroid Build Coastguard Worker    st_api_destroy_drawable(&osbuffer->base);
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker    FREE(osbuffer);
508*61046927SAndroid Build Coastguard Worker }
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker /**********************************************************************/
513*61046927SAndroid Build Coastguard Worker /*****                    Public Functions                        *****/
514*61046927SAndroid Build Coastguard Worker /**********************************************************************/
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker /**
518*61046927SAndroid Build Coastguard Worker  * Create an Off-Screen Mesa rendering context.  The only attribute needed is
519*61046927SAndroid Build Coastguard Worker  * an RGBA vs Color-Index mode flag.
520*61046927SAndroid Build Coastguard Worker  *
521*61046927SAndroid Build Coastguard Worker  * Input:  format - Must be GL_RGBA
522*61046927SAndroid Build Coastguard Worker  *         sharelist - specifies another OSMesaContext with which to share
523*61046927SAndroid Build Coastguard Worker  *                     display lists.  NULL indicates no sharing.
524*61046927SAndroid Build Coastguard Worker  * Return:  an OSMesaContext or 0 if error
525*61046927SAndroid Build Coastguard Worker  */
526*61046927SAndroid Build Coastguard Worker GLAPI OSMesaContext GLAPIENTRY
OSMesaCreateContext(GLenum format,OSMesaContext sharelist)527*61046927SAndroid Build Coastguard Worker OSMesaCreateContext(GLenum format, OSMesaContext sharelist)
528*61046927SAndroid Build Coastguard Worker {
529*61046927SAndroid Build Coastguard Worker    return OSMesaCreateContextExt(format, 24, 8, 0, sharelist);
530*61046927SAndroid Build Coastguard Worker }
531*61046927SAndroid Build Coastguard Worker 
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker /**
534*61046927SAndroid Build Coastguard Worker  * New in Mesa 3.5
535*61046927SAndroid Build Coastguard Worker  *
536*61046927SAndroid Build Coastguard Worker  * Create context and specify size of ancillary buffers.
537*61046927SAndroid Build Coastguard Worker  */
538*61046927SAndroid Build Coastguard Worker GLAPI OSMesaContext GLAPIENTRY
OSMesaCreateContextExt(GLenum format,GLint depthBits,GLint stencilBits,GLint accumBits,OSMesaContext sharelist)539*61046927SAndroid Build Coastguard Worker OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits,
540*61046927SAndroid Build Coastguard Worker                        GLint accumBits, OSMesaContext sharelist)
541*61046927SAndroid Build Coastguard Worker {
542*61046927SAndroid Build Coastguard Worker    int attribs[100], n = 0;
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker    attribs[n++] = OSMESA_FORMAT;
545*61046927SAndroid Build Coastguard Worker    attribs[n++] = format;
546*61046927SAndroid Build Coastguard Worker    attribs[n++] = OSMESA_DEPTH_BITS;
547*61046927SAndroid Build Coastguard Worker    attribs[n++] = depthBits;
548*61046927SAndroid Build Coastguard Worker    attribs[n++] = OSMESA_STENCIL_BITS;
549*61046927SAndroid Build Coastguard Worker    attribs[n++] = stencilBits;
550*61046927SAndroid Build Coastguard Worker    attribs[n++] = OSMESA_ACCUM_BITS;
551*61046927SAndroid Build Coastguard Worker    attribs[n++] = accumBits;
552*61046927SAndroid Build Coastguard Worker    attribs[n++] = 0;
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    return OSMesaCreateContextAttribs(attribs, sharelist);
555*61046927SAndroid Build Coastguard Worker }
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker /**
559*61046927SAndroid Build Coastguard Worker  * New in Mesa 11.2
560*61046927SAndroid Build Coastguard Worker  *
561*61046927SAndroid Build Coastguard Worker  * Create context with attribute list.
562*61046927SAndroid Build Coastguard Worker  */
563*61046927SAndroid Build Coastguard Worker GLAPI OSMesaContext GLAPIENTRY
OSMesaCreateContextAttribs(const int * attribList,OSMesaContext sharelist)564*61046927SAndroid Build Coastguard Worker OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
565*61046927SAndroid Build Coastguard Worker {
566*61046927SAndroid Build Coastguard Worker    OSMesaContext osmesa;
567*61046927SAndroid Build Coastguard Worker    struct st_context *st_shared;
568*61046927SAndroid Build Coastguard Worker    enum st_context_error st_error = 0;
569*61046927SAndroid Build Coastguard Worker    struct st_context_attribs attribs;
570*61046927SAndroid Build Coastguard Worker    GLenum format = GL_RGBA;
571*61046927SAndroid Build Coastguard Worker    int depthBits = 0, stencilBits = 0, accumBits = 0;
572*61046927SAndroid Build Coastguard Worker    int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0;
573*61046927SAndroid Build Coastguard Worker    int i;
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker    if (sharelist) {
576*61046927SAndroid Build Coastguard Worker       st_shared = sharelist->st;
577*61046927SAndroid Build Coastguard Worker    }
578*61046927SAndroid Build Coastguard Worker    else {
579*61046927SAndroid Build Coastguard Worker       st_shared = NULL;
580*61046927SAndroid Build Coastguard Worker    }
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    for (i = 0; attribList[i]; i += 2) {
583*61046927SAndroid Build Coastguard Worker       switch (attribList[i]) {
584*61046927SAndroid Build Coastguard Worker       case OSMESA_FORMAT:
585*61046927SAndroid Build Coastguard Worker          format = attribList[i+1];
586*61046927SAndroid Build Coastguard Worker          switch (format) {
587*61046927SAndroid Build Coastguard Worker          case OSMESA_COLOR_INDEX:
588*61046927SAndroid Build Coastguard Worker          case OSMESA_RGBA:
589*61046927SAndroid Build Coastguard Worker          case OSMESA_BGRA:
590*61046927SAndroid Build Coastguard Worker          case OSMESA_ARGB:
591*61046927SAndroid Build Coastguard Worker          case OSMESA_RGB:
592*61046927SAndroid Build Coastguard Worker          case OSMESA_BGR:
593*61046927SAndroid Build Coastguard Worker          case OSMESA_RGB_565:
594*61046927SAndroid Build Coastguard Worker             /* legal */
595*61046927SAndroid Build Coastguard Worker             break;
596*61046927SAndroid Build Coastguard Worker          default:
597*61046927SAndroid Build Coastguard Worker             return NULL;
598*61046927SAndroid Build Coastguard Worker          }
599*61046927SAndroid Build Coastguard Worker          break;
600*61046927SAndroid Build Coastguard Worker       case OSMESA_DEPTH_BITS:
601*61046927SAndroid Build Coastguard Worker          depthBits = attribList[i+1];
602*61046927SAndroid Build Coastguard Worker          if (depthBits < 0)
603*61046927SAndroid Build Coastguard Worker             return NULL;
604*61046927SAndroid Build Coastguard Worker          break;
605*61046927SAndroid Build Coastguard Worker       case OSMESA_STENCIL_BITS:
606*61046927SAndroid Build Coastguard Worker          stencilBits = attribList[i+1];
607*61046927SAndroid Build Coastguard Worker          if (stencilBits < 0)
608*61046927SAndroid Build Coastguard Worker             return NULL;
609*61046927SAndroid Build Coastguard Worker          break;
610*61046927SAndroid Build Coastguard Worker       case OSMESA_ACCUM_BITS:
611*61046927SAndroid Build Coastguard Worker          accumBits = attribList[i+1];
612*61046927SAndroid Build Coastguard Worker          if (accumBits < 0)
613*61046927SAndroid Build Coastguard Worker             return NULL;
614*61046927SAndroid Build Coastguard Worker          break;
615*61046927SAndroid Build Coastguard Worker       case OSMESA_PROFILE:
616*61046927SAndroid Build Coastguard Worker          profile = attribList[i+1];
617*61046927SAndroid Build Coastguard Worker          if (profile != OSMESA_CORE_PROFILE &&
618*61046927SAndroid Build Coastguard Worker              profile != OSMESA_COMPAT_PROFILE)
619*61046927SAndroid Build Coastguard Worker             return NULL;
620*61046927SAndroid Build Coastguard Worker          break;
621*61046927SAndroid Build Coastguard Worker       case OSMESA_CONTEXT_MAJOR_VERSION:
622*61046927SAndroid Build Coastguard Worker          version_major = attribList[i+1];
623*61046927SAndroid Build Coastguard Worker          if (version_major < 1)
624*61046927SAndroid Build Coastguard Worker             return NULL;
625*61046927SAndroid Build Coastguard Worker          break;
626*61046927SAndroid Build Coastguard Worker       case OSMESA_CONTEXT_MINOR_VERSION:
627*61046927SAndroid Build Coastguard Worker          version_minor = attribList[i+1];
628*61046927SAndroid Build Coastguard Worker          if (version_minor < 0)
629*61046927SAndroid Build Coastguard Worker             return NULL;
630*61046927SAndroid Build Coastguard Worker          break;
631*61046927SAndroid Build Coastguard Worker       case 0:
632*61046927SAndroid Build Coastguard Worker          /* end of list */
633*61046927SAndroid Build Coastguard Worker          break;
634*61046927SAndroid Build Coastguard Worker       default:
635*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n");
636*61046927SAndroid Build Coastguard Worker          return NULL;
637*61046927SAndroid Build Coastguard Worker       }
638*61046927SAndroid Build Coastguard Worker    }
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
641*61046927SAndroid Build Coastguard Worker    if (!osmesa)
642*61046927SAndroid Build Coastguard Worker       return NULL;
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    /* Choose depth/stencil/accum buffer formats */
645*61046927SAndroid Build Coastguard Worker    if (accumBits > 0) {
646*61046927SAndroid Build Coastguard Worker       osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM;
647*61046927SAndroid Build Coastguard Worker    }
648*61046927SAndroid Build Coastguard Worker    if (depthBits > 0 && stencilBits > 0) {
649*61046927SAndroid Build Coastguard Worker       osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
650*61046927SAndroid Build Coastguard Worker    }
651*61046927SAndroid Build Coastguard Worker    else if (stencilBits > 0) {
652*61046927SAndroid Build Coastguard Worker       osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT;
653*61046927SAndroid Build Coastguard Worker    }
654*61046927SAndroid Build Coastguard Worker    else if (depthBits >= 24) {
655*61046927SAndroid Build Coastguard Worker       osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
656*61046927SAndroid Build Coastguard Worker    }
657*61046927SAndroid Build Coastguard Worker    else if (depthBits >= 16) {
658*61046927SAndroid Build Coastguard Worker       osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
659*61046927SAndroid Build Coastguard Worker    }
660*61046927SAndroid Build Coastguard Worker 
661*61046927SAndroid Build Coastguard Worker    /*
662*61046927SAndroid Build Coastguard Worker     * Create the rendering context
663*61046927SAndroid Build Coastguard Worker     */
664*61046927SAndroid Build Coastguard Worker    memset(&attribs, 0, sizeof(attribs));
665*61046927SAndroid Build Coastguard Worker    attribs.profile = (profile == OSMESA_CORE_PROFILE)
666*61046927SAndroid Build Coastguard Worker       ? API_OPENGL_CORE : API_OPENGL_COMPAT;
667*61046927SAndroid Build Coastguard Worker    attribs.major = version_major;
668*61046927SAndroid Build Coastguard Worker    attribs.minor = version_minor;
669*61046927SAndroid Build Coastguard Worker    attribs.flags = 0;  /* ST_CONTEXT_FLAG_x */
670*61046927SAndroid Build Coastguard Worker    attribs.options.force_glsl_extensions_warn = false;
671*61046927SAndroid Build Coastguard Worker    attribs.options.disable_blend_func_extended = false;
672*61046927SAndroid Build Coastguard Worker    attribs.options.disable_glsl_line_continuations = false;
673*61046927SAndroid Build Coastguard Worker    attribs.options.force_glsl_version = 0;
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker    osmesa_init_st_visual(&attribs.visual,
676*61046927SAndroid Build Coastguard Worker                          PIPE_FORMAT_NONE,
677*61046927SAndroid Build Coastguard Worker                          osmesa->depth_stencil_format,
678*61046927SAndroid Build Coastguard Worker                          osmesa->accum_format);
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker    osmesa->st = st_api_create_context(get_st_manager(),
681*61046927SAndroid Build Coastguard Worker                                          &attribs, &st_error, st_shared);
682*61046927SAndroid Build Coastguard Worker    if (!osmesa->st) {
683*61046927SAndroid Build Coastguard Worker       FREE(osmesa);
684*61046927SAndroid Build Coastguard Worker       return NULL;
685*61046927SAndroid Build Coastguard Worker    }
686*61046927SAndroid Build Coastguard Worker 
687*61046927SAndroid Build Coastguard Worker    osmesa->st->frontend_context = osmesa;
688*61046927SAndroid Build Coastguard Worker 
689*61046927SAndroid Build Coastguard Worker    osmesa->format = format;
690*61046927SAndroid Build Coastguard Worker    osmesa->user_row_length = 0;
691*61046927SAndroid Build Coastguard Worker    osmesa->y_up = GL_TRUE;
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    return osmesa;
694*61046927SAndroid Build Coastguard Worker }
695*61046927SAndroid Build Coastguard Worker 
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker 
698*61046927SAndroid Build Coastguard Worker /**
699*61046927SAndroid Build Coastguard Worker  * Destroy an Off-Screen Mesa rendering context.
700*61046927SAndroid Build Coastguard Worker  *
701*61046927SAndroid Build Coastguard Worker  * \param osmesa  the context to destroy
702*61046927SAndroid Build Coastguard Worker  */
703*61046927SAndroid Build Coastguard Worker GLAPI void GLAPIENTRY
OSMesaDestroyContext(OSMesaContext osmesa)704*61046927SAndroid Build Coastguard Worker OSMesaDestroyContext(OSMesaContext osmesa)
705*61046927SAndroid Build Coastguard Worker {
706*61046927SAndroid Build Coastguard Worker    if (osmesa) {
707*61046927SAndroid Build Coastguard Worker       pp_free(osmesa->pp);
708*61046927SAndroid Build Coastguard Worker       st_destroy_context(osmesa->st);
709*61046927SAndroid Build Coastguard Worker       free(osmesa->zs);
710*61046927SAndroid Build Coastguard Worker       FREE(osmesa);
711*61046927SAndroid Build Coastguard Worker    }
712*61046927SAndroid Build Coastguard Worker }
713*61046927SAndroid Build Coastguard Worker 
714*61046927SAndroid Build Coastguard Worker 
715*61046927SAndroid Build Coastguard Worker /**
716*61046927SAndroid Build Coastguard Worker  * Bind an OSMesaContext to an image buffer.  The image buffer is just a
717*61046927SAndroid Build Coastguard Worker  * block of memory which the client provides.  Its size must be at least
718*61046927SAndroid Build Coastguard Worker  * as large as width*height*pixelSize.  Its address should be a multiple
719*61046927SAndroid Build Coastguard Worker  * of 4 if using RGBA mode.
720*61046927SAndroid Build Coastguard Worker  *
721*61046927SAndroid Build Coastguard Worker  * By default, image data is stored in the order of glDrawPixels: row-major
722*61046927SAndroid Build Coastguard Worker  * order with the lower-left image pixel stored in the first array position
723*61046927SAndroid Build Coastguard Worker  * (ie. bottom-to-top).
724*61046927SAndroid Build Coastguard Worker  *
725*61046927SAndroid Build Coastguard Worker  * If the context's viewport hasn't been initialized yet, it will now be
726*61046927SAndroid Build Coastguard Worker  * initialized to (0,0,width,height).
727*61046927SAndroid Build Coastguard Worker  *
728*61046927SAndroid Build Coastguard Worker  * Input:  osmesa - the rendering context
729*61046927SAndroid Build Coastguard Worker  *         buffer - the image buffer memory
730*61046927SAndroid Build Coastguard Worker  *         type - data type for pixel components
731*61046927SAndroid Build Coastguard Worker  *                GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT
732*61046927SAndroid Build Coastguard Worker  *                or GL_FLOAT.
733*61046927SAndroid Build Coastguard Worker  *         width, height - size of image buffer in pixels, at least 1
734*61046927SAndroid Build Coastguard Worker  * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
735*61046927SAndroid Build Coastguard Worker  *          invalid type, invalid size, etc.
736*61046927SAndroid Build Coastguard Worker  */
737*61046927SAndroid Build Coastguard Worker GLAPI GLboolean GLAPIENTRY
OSMesaMakeCurrent(OSMesaContext osmesa,void * buffer,GLenum type,GLsizei width,GLsizei height)738*61046927SAndroid Build Coastguard Worker OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
739*61046927SAndroid Build Coastguard Worker                   GLsizei width, GLsizei height)
740*61046927SAndroid Build Coastguard Worker {
741*61046927SAndroid Build Coastguard Worker    enum pipe_format color_format;
742*61046927SAndroid Build Coastguard Worker 
743*61046927SAndroid Build Coastguard Worker    if (!osmesa && !buffer) {
744*61046927SAndroid Build Coastguard Worker       st_api_make_current(NULL, NULL, NULL);
745*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
746*61046927SAndroid Build Coastguard Worker    }
747*61046927SAndroid Build Coastguard Worker 
748*61046927SAndroid Build Coastguard Worker    if (!osmesa || !buffer || width < 1 || height < 1) {
749*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
750*61046927SAndroid Build Coastguard Worker    }
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker    color_format = osmesa_choose_format(osmesa->format, type);
753*61046927SAndroid Build Coastguard Worker    if (color_format == PIPE_FORMAT_NONE) {
754*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n");
755*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
756*61046927SAndroid Build Coastguard Worker    }
757*61046927SAndroid Build Coastguard Worker 
758*61046927SAndroid Build Coastguard Worker    /* See if we already have a buffer that uses these pixel formats */
759*61046927SAndroid Build Coastguard Worker    if (osmesa->current_buffer &&
760*61046927SAndroid Build Coastguard Worker        (osmesa->current_buffer->visual.color_format != color_format ||
761*61046927SAndroid Build Coastguard Worker         osmesa->current_buffer->visual.depth_stencil_format != osmesa->depth_stencil_format ||
762*61046927SAndroid Build Coastguard Worker         osmesa->current_buffer->visual.accum_format != osmesa->accum_format ||
763*61046927SAndroid Build Coastguard Worker         osmesa->current_buffer->width != width ||
764*61046927SAndroid Build Coastguard Worker         osmesa->current_buffer->height != height)) {
765*61046927SAndroid Build Coastguard Worker       osmesa_destroy_buffer(osmesa->current_buffer);
766*61046927SAndroid Build Coastguard Worker       osmesa->current_buffer = NULL;
767*61046927SAndroid Build Coastguard Worker    }
768*61046927SAndroid Build Coastguard Worker 
769*61046927SAndroid Build Coastguard Worker    if (!osmesa->current_buffer) {
770*61046927SAndroid Build Coastguard Worker       osmesa->current_buffer = osmesa_create_buffer(color_format,
771*61046927SAndroid Build Coastguard Worker                                       osmesa->depth_stencil_format,
772*61046927SAndroid Build Coastguard Worker                                       osmesa->accum_format);
773*61046927SAndroid Build Coastguard Worker    }
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = osmesa->current_buffer;
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker    osbuffer->width = width;
778*61046927SAndroid Build Coastguard Worker    osbuffer->height = height;
779*61046927SAndroid Build Coastguard Worker    osbuffer->map = buffer;
780*61046927SAndroid Build Coastguard Worker 
781*61046927SAndroid Build Coastguard Worker    osmesa->type = type;
782*61046927SAndroid Build Coastguard Worker 
783*61046927SAndroid Build Coastguard Worker    st_api_make_current(osmesa->st, &osbuffer->base, &osbuffer->base);
784*61046927SAndroid Build Coastguard Worker 
785*61046927SAndroid Build Coastguard Worker    /* XXX: We should probably load the current color value into the buffer here
786*61046927SAndroid Build Coastguard Worker     * to match classic swrast behavior (context's fb starts with the contents of
787*61046927SAndroid Build Coastguard Worker     * your pixel buffer).
788*61046927SAndroid Build Coastguard Worker     */
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker    if (!osmesa->ever_used) {
791*61046927SAndroid Build Coastguard Worker       /* one-time init, just postprocessing for now */
792*61046927SAndroid Build Coastguard Worker       bool any_pp_enabled = false;
793*61046927SAndroid Build Coastguard Worker       unsigned i;
794*61046927SAndroid Build Coastguard Worker 
795*61046927SAndroid Build Coastguard Worker       for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) {
796*61046927SAndroid Build Coastguard Worker          if (osmesa->pp_enabled[i]) {
797*61046927SAndroid Build Coastguard Worker             any_pp_enabled = true;
798*61046927SAndroid Build Coastguard Worker             break;
799*61046927SAndroid Build Coastguard Worker          }
800*61046927SAndroid Build Coastguard Worker       }
801*61046927SAndroid Build Coastguard Worker 
802*61046927SAndroid Build Coastguard Worker       if (any_pp_enabled) {
803*61046927SAndroid Build Coastguard Worker          osmesa->pp = pp_init(osmesa->st->pipe,
804*61046927SAndroid Build Coastguard Worker                               osmesa->pp_enabled,
805*61046927SAndroid Build Coastguard Worker                               osmesa->st->cso_context,
806*61046927SAndroid Build Coastguard Worker                               osmesa->st,
807*61046927SAndroid Build Coastguard Worker                               st_context_invalidate_state);
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker          pp_init_fbos(osmesa->pp, width, height);
810*61046927SAndroid Build Coastguard Worker       }
811*61046927SAndroid Build Coastguard Worker 
812*61046927SAndroid Build Coastguard Worker       osmesa->ever_used = true;
813*61046927SAndroid Build Coastguard Worker    }
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
816*61046927SAndroid Build Coastguard Worker }
817*61046927SAndroid Build Coastguard Worker 
818*61046927SAndroid Build Coastguard Worker 
819*61046927SAndroid Build Coastguard Worker 
820*61046927SAndroid Build Coastguard Worker GLAPI OSMesaContext GLAPIENTRY
OSMesaGetCurrentContext(void)821*61046927SAndroid Build Coastguard Worker OSMesaGetCurrentContext(void)
822*61046927SAndroid Build Coastguard Worker {
823*61046927SAndroid Build Coastguard Worker    struct st_context *st = st_api_get_current();
824*61046927SAndroid Build Coastguard Worker    return st ? (OSMesaContext) st->frontend_context : NULL;
825*61046927SAndroid Build Coastguard Worker }
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker 
829*61046927SAndroid Build Coastguard Worker GLAPI void GLAPIENTRY
OSMesaPixelStore(GLint pname,GLint value)830*61046927SAndroid Build Coastguard Worker OSMesaPixelStore(GLint pname, GLint value)
831*61046927SAndroid Build Coastguard Worker {
832*61046927SAndroid Build Coastguard Worker    OSMesaContext osmesa = OSMesaGetCurrentContext();
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    switch (pname) {
835*61046927SAndroid Build Coastguard Worker    case OSMESA_ROW_LENGTH:
836*61046927SAndroid Build Coastguard Worker       osmesa->user_row_length = value;
837*61046927SAndroid Build Coastguard Worker       break;
838*61046927SAndroid Build Coastguard Worker    case OSMESA_Y_UP:
839*61046927SAndroid Build Coastguard Worker       osmesa->y_up = value ? GL_TRUE : GL_FALSE;
840*61046927SAndroid Build Coastguard Worker       break;
841*61046927SAndroid Build Coastguard Worker    default:
842*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n");
843*61046927SAndroid Build Coastguard Worker       return;
844*61046927SAndroid Build Coastguard Worker    }
845*61046927SAndroid Build Coastguard Worker }
846*61046927SAndroid Build Coastguard Worker 
847*61046927SAndroid Build Coastguard Worker 
848*61046927SAndroid Build Coastguard Worker GLAPI void GLAPIENTRY
OSMesaGetIntegerv(GLint pname,GLint * value)849*61046927SAndroid Build Coastguard Worker OSMesaGetIntegerv(GLint pname, GLint *value)
850*61046927SAndroid Build Coastguard Worker {
851*61046927SAndroid Build Coastguard Worker    OSMesaContext osmesa = OSMesaGetCurrentContext();
852*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL;
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker    switch (pname) {
855*61046927SAndroid Build Coastguard Worker    case OSMESA_WIDTH:
856*61046927SAndroid Build Coastguard Worker       *value = osbuffer ? osbuffer->width : 0;
857*61046927SAndroid Build Coastguard Worker       return;
858*61046927SAndroid Build Coastguard Worker    case OSMESA_HEIGHT:
859*61046927SAndroid Build Coastguard Worker       *value = osbuffer ? osbuffer->height : 0;
860*61046927SAndroid Build Coastguard Worker       return;
861*61046927SAndroid Build Coastguard Worker    case OSMESA_FORMAT:
862*61046927SAndroid Build Coastguard Worker       *value = osmesa->format;
863*61046927SAndroid Build Coastguard Worker       return;
864*61046927SAndroid Build Coastguard Worker    case OSMESA_TYPE:
865*61046927SAndroid Build Coastguard Worker       /* current color buffer's data type */
866*61046927SAndroid Build Coastguard Worker       *value = osmesa->type;
867*61046927SAndroid Build Coastguard Worker       return;
868*61046927SAndroid Build Coastguard Worker    case OSMESA_ROW_LENGTH:
869*61046927SAndroid Build Coastguard Worker       *value = osmesa->user_row_length;
870*61046927SAndroid Build Coastguard Worker       return;
871*61046927SAndroid Build Coastguard Worker    case OSMESA_Y_UP:
872*61046927SAndroid Build Coastguard Worker       *value = osmesa->y_up;
873*61046927SAndroid Build Coastguard Worker       return;
874*61046927SAndroid Build Coastguard Worker    case OSMESA_MAX_WIDTH:
875*61046927SAndroid Build Coastguard Worker       FALLTHROUGH;
876*61046927SAndroid Build Coastguard Worker    case OSMESA_MAX_HEIGHT:
877*61046927SAndroid Build Coastguard Worker       {
878*61046927SAndroid Build Coastguard Worker          struct pipe_screen *screen = get_st_manager()->screen;
879*61046927SAndroid Build Coastguard Worker          *value = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
880*61046927SAndroid Build Coastguard Worker       }
881*61046927SAndroid Build Coastguard Worker       return;
882*61046927SAndroid Build Coastguard Worker    default:
883*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n");
884*61046927SAndroid Build Coastguard Worker       return;
885*61046927SAndroid Build Coastguard Worker    }
886*61046927SAndroid Build Coastguard Worker }
887*61046927SAndroid Build Coastguard Worker 
888*61046927SAndroid Build Coastguard Worker 
889*61046927SAndroid Build Coastguard Worker /**
890*61046927SAndroid Build Coastguard Worker  * Return information about the depth buffer associated with an OSMesa context.
891*61046927SAndroid Build Coastguard Worker  * Input:  c - the OSMesa context
892*61046927SAndroid Build Coastguard Worker  * Output:  width, height - size of buffer in pixels
893*61046927SAndroid Build Coastguard Worker  *          bytesPerValue - bytes per depth value (2 or 4)
894*61046927SAndroid Build Coastguard Worker  *          buffer - pointer to depth buffer values
895*61046927SAndroid Build Coastguard Worker  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
896*61046927SAndroid Build Coastguard Worker  */
897*61046927SAndroid Build Coastguard Worker GLAPI GLboolean GLAPIENTRY
OSMesaGetDepthBuffer(OSMesaContext c,GLint * width,GLint * height,GLint * bytesPerValue,void ** buffer)898*61046927SAndroid Build Coastguard Worker OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height,
899*61046927SAndroid Build Coastguard Worker                      GLint *bytesPerValue, void **buffer)
900*61046927SAndroid Build Coastguard Worker {
901*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = c->current_buffer;
902*61046927SAndroid Build Coastguard Worker    struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL];
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker    if (!res) {
905*61046927SAndroid Build Coastguard Worker       *width = 0;
906*61046927SAndroid Build Coastguard Worker       *height = 0;
907*61046927SAndroid Build Coastguard Worker       *bytesPerValue = 0;
908*61046927SAndroid Build Coastguard Worker       *buffer = NULL;
909*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
910*61046927SAndroid Build Coastguard Worker    }
911*61046927SAndroid Build Coastguard Worker 
912*61046927SAndroid Build Coastguard Worker    *width = res->width0;
913*61046927SAndroid Build Coastguard Worker    *height = res->height0;
914*61046927SAndroid Build Coastguard Worker    *bytesPerValue = util_format_get_blocksize(res->format);
915*61046927SAndroid Build Coastguard Worker 
916*61046927SAndroid Build Coastguard Worker    if (!c->zs) {
917*61046927SAndroid Build Coastguard Worker       c->zs_stride = *width * *bytesPerValue;
918*61046927SAndroid Build Coastguard Worker       c->zs = calloc(c->zs_stride, *height);
919*61046927SAndroid Build Coastguard Worker       if (!c->zs)
920*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
921*61046927SAndroid Build Coastguard Worker 
922*61046927SAndroid Build Coastguard Worker       osmesa_read_buffer(c, res, c->zs, c->zs_stride, true);
923*61046927SAndroid Build Coastguard Worker    }
924*61046927SAndroid Build Coastguard Worker 
925*61046927SAndroid Build Coastguard Worker    *buffer = c->zs;
926*61046927SAndroid Build Coastguard Worker 
927*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
928*61046927SAndroid Build Coastguard Worker }
929*61046927SAndroid Build Coastguard Worker 
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker /**
932*61046927SAndroid Build Coastguard Worker  * Return the color buffer associated with an OSMesa context.
933*61046927SAndroid Build Coastguard Worker  * Input:  c - the OSMesa context
934*61046927SAndroid Build Coastguard Worker  * Output:  width, height - size of buffer in pixels
935*61046927SAndroid Build Coastguard Worker  *          format - the pixel format (OSMESA_FORMAT)
936*61046927SAndroid Build Coastguard Worker  *          buffer - pointer to color buffer values
937*61046927SAndroid Build Coastguard Worker  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
938*61046927SAndroid Build Coastguard Worker  */
939*61046927SAndroid Build Coastguard Worker GLAPI GLboolean GLAPIENTRY
OSMesaGetColorBuffer(OSMesaContext osmesa,GLint * width,GLint * height,GLint * format,void ** buffer)940*61046927SAndroid Build Coastguard Worker OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width,
941*61046927SAndroid Build Coastguard Worker                       GLint *height, GLint *format, void **buffer)
942*61046927SAndroid Build Coastguard Worker {
943*61046927SAndroid Build Coastguard Worker    struct osmesa_buffer *osbuffer = osmesa->current_buffer;
944*61046927SAndroid Build Coastguard Worker 
945*61046927SAndroid Build Coastguard Worker    if (osbuffer) {
946*61046927SAndroid Build Coastguard Worker       *width = osbuffer->width;
947*61046927SAndroid Build Coastguard Worker       *height = osbuffer->height;
948*61046927SAndroid Build Coastguard Worker       *format = osmesa->format;
949*61046927SAndroid Build Coastguard Worker       *buffer = osbuffer->map;
950*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
951*61046927SAndroid Build Coastguard Worker    }
952*61046927SAndroid Build Coastguard Worker    else {
953*61046927SAndroid Build Coastguard Worker       *width = 0;
954*61046927SAndroid Build Coastguard Worker       *height = 0;
955*61046927SAndroid Build Coastguard Worker       *format = 0;
956*61046927SAndroid Build Coastguard Worker       *buffer = 0;
957*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
958*61046927SAndroid Build Coastguard Worker    }
959*61046927SAndroid Build Coastguard Worker }
960*61046927SAndroid Build Coastguard Worker 
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker struct name_function
963*61046927SAndroid Build Coastguard Worker {
964*61046927SAndroid Build Coastguard Worker    const char *Name;
965*61046927SAndroid Build Coastguard Worker    OSMESAproc Function;
966*61046927SAndroid Build Coastguard Worker };
967*61046927SAndroid Build Coastguard Worker 
968*61046927SAndroid Build Coastguard Worker static struct name_function functions[] = {
969*61046927SAndroid Build Coastguard Worker    { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
970*61046927SAndroid Build Coastguard Worker    { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
971*61046927SAndroid Build Coastguard Worker    { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs },
972*61046927SAndroid Build Coastguard Worker    { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
973*61046927SAndroid Build Coastguard Worker    { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
974*61046927SAndroid Build Coastguard Worker    { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
975*61046927SAndroid Build Coastguard Worker    { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore },
976*61046927SAndroid Build Coastguard Worker    { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
977*61046927SAndroid Build Coastguard Worker    { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
978*61046927SAndroid Build Coastguard Worker    { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
979*61046927SAndroid Build Coastguard Worker    { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
980*61046927SAndroid Build Coastguard Worker    { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
981*61046927SAndroid Build Coastguard Worker    { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess },
982*61046927SAndroid Build Coastguard Worker    { NULL, NULL }
983*61046927SAndroid Build Coastguard Worker };
984*61046927SAndroid Build Coastguard Worker 
985*61046927SAndroid Build Coastguard Worker 
986*61046927SAndroid Build Coastguard Worker GLAPI OSMESAproc GLAPIENTRY
OSMesaGetProcAddress(const char * funcName)987*61046927SAndroid Build Coastguard Worker OSMesaGetProcAddress(const char *funcName)
988*61046927SAndroid Build Coastguard Worker {
989*61046927SAndroid Build Coastguard Worker    int i;
990*61046927SAndroid Build Coastguard Worker    for (i = 0; functions[i].Name; i++) {
991*61046927SAndroid Build Coastguard Worker       if (strcmp(functions[i].Name, funcName) == 0)
992*61046927SAndroid Build Coastguard Worker          return functions[i].Function;
993*61046927SAndroid Build Coastguard Worker    }
994*61046927SAndroid Build Coastguard Worker    return _glapi_get_proc_address(funcName);
995*61046927SAndroid Build Coastguard Worker }
996*61046927SAndroid Build Coastguard Worker 
997*61046927SAndroid Build Coastguard Worker 
998*61046927SAndroid Build Coastguard Worker GLAPI void GLAPIENTRY
OSMesaColorClamp(GLboolean enable)999*61046927SAndroid Build Coastguard Worker OSMesaColorClamp(GLboolean enable)
1000*61046927SAndroid Build Coastguard Worker {
1001*61046927SAndroid Build Coastguard Worker    extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp);
1002*61046927SAndroid Build Coastguard Worker 
1003*61046927SAndroid Build Coastguard Worker    _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
1004*61046927SAndroid Build Coastguard Worker                     enable ? GL_TRUE : GL_FIXED_ONLY_ARB);
1005*61046927SAndroid Build Coastguard Worker }
1006*61046927SAndroid Build Coastguard Worker 
1007*61046927SAndroid Build Coastguard Worker 
1008*61046927SAndroid Build Coastguard Worker GLAPI void GLAPIENTRY
OSMesaPostprocess(OSMesaContext osmesa,const char * filter,unsigned enable_value)1009*61046927SAndroid Build Coastguard Worker OSMesaPostprocess(OSMesaContext osmesa, const char *filter,
1010*61046927SAndroid Build Coastguard Worker                   unsigned enable_value)
1011*61046927SAndroid Build Coastguard Worker {
1012*61046927SAndroid Build Coastguard Worker    if (!osmesa->ever_used) {
1013*61046927SAndroid Build Coastguard Worker       /* We can only enable/disable postprocess filters before a context
1014*61046927SAndroid Build Coastguard Worker        * is made current for the first time.
1015*61046927SAndroid Build Coastguard Worker        */
1016*61046927SAndroid Build Coastguard Worker       unsigned i;
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker       for (i = 0; i < PP_FILTERS; i++) {
1019*61046927SAndroid Build Coastguard Worker          if (strcmp(pp_filters[i].name, filter) == 0) {
1020*61046927SAndroid Build Coastguard Worker             osmesa->pp_enabled[i] = enable_value;
1021*61046927SAndroid Build Coastguard Worker             return;
1022*61046927SAndroid Build Coastguard Worker          }
1023*61046927SAndroid Build Coastguard Worker       }
1024*61046927SAndroid Build Coastguard Worker       debug_warning("OSMesaPostprocess(unknown filter)\n");
1025*61046927SAndroid Build Coastguard Worker    }
1026*61046927SAndroid Build Coastguard Worker    else {
1027*61046927SAndroid Build Coastguard Worker       debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n");
1028*61046927SAndroid Build Coastguard Worker    }
1029*61046927SAndroid Build Coastguard Worker }
1030