Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright (c) 2013  Brian Paul   All Rights Reserved.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included
12
 * in all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 * OTHER DEALINGS IN THE SOFTWARE.
21
 */
22
 
23
 
24
/*
25
 * Off-Screen rendering into client memory.
26
 * State tracker for gallium (for softpipe and llvmpipe)
27
 *
28
 * Notes:
29
 *
30
 * If Gallium is built with LLVM support we use the llvmpipe driver.
31
 * Otherwise we use softpipe.  The GALLIUM_DRIVER environment variable
32
 * may be set to "softpipe" or "llvmpipe" to override.
33
 *
34
 * With softpipe we could render directly into the user's buffer by using a
35
 * display target resource.  However, softpipe doesn't suport "upside-down"
36
 * rendering which would be needed for the OSMESA_Y_UP=TRUE case.
37
 *
38
 * With llvmpipe we could only render directly into the user's buffer when its
39
 * width and height is a multiple of the tile size (64 pixels).
40
 *
41
 * Because of these constraints we always render into ordinary resources then
42
 * copy the results to the user's buffer in the flush_front() function which
43
 * is called when the app calls glFlush/Finish.
44
 *
45
 * In general, the OSMesa interface is pretty ugly and not a good match
46
 * for Gallium.  But we're interested in doing the best we can to preserve
47
 * application portability.  With a little work we could come up with a
48
 * much nicer, new off-screen Gallium interface...
49
 */
50
 
51
 
52
#include "GL/osmesa.h"
53
 
54
#include "glapi/glapi.h"  /* for OSMesaGetProcAddress below */
55
 
56
#include "pipe/p_context.h"
57
#include "pipe/p_screen.h"
58
#include "pipe/p_state.h"
59
 
60
#include "util/u_atomic.h"
61
#include "util/u_box.h"
62
#include "util/u_format.h"
63
#include "util/u_memory.h"
64
 
65
#include "state_tracker/st_api.h"
66
#include "state_tracker/st_gl_api.h"
67
 
68
 
69
 
70
extern struct pipe_screen *
71
osmesa_create_screen(void);
72
 
73
 
74
 
75
struct osmesa_buffer
76
{
77
   struct st_framebuffer_iface *stfb;
78
   struct st_visual visual;
79
   unsigned width, height;
80
 
81
   struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
82
 
83
   void *map;
84
 
85
   struct osmesa_buffer *next;  /**< next in linked list */
86
};
87
 
88
 
89
struct osmesa_context
90
{
91
   struct st_context_iface *stctx;
92
 
93
   struct osmesa_buffer *current_buffer;
94
 
95
   enum pipe_format depth_stencil_format, accum_format;
96
 
97
   GLenum format;         /*< User-specified context format */
98
   GLenum type;           /*< Buffer's data type */
99
   GLint user_row_length; /*< user-specified number of pixels per row */
100
   GLboolean y_up;        /*< TRUE  -> Y increases upward */
101
                          /*< FALSE -> Y increases downward */
102
};
103
 
104
 
105
/**
106
 * Linked list of all osmesa_buffers.
107
 * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to
108
 * the next unless the color/depth/stencil/accum formats change.
109
 * We have to do this to be compatible with the original OSMesa implementation
110
 * because some apps call OSMesaMakeCurrent() several times during rendering
111
 * a frame.
112
 */
113
static struct osmesa_buffer *BufferList = NULL;
114
 
115
 
116
/**
117
 * Called from the ST manager.
118
 */
119
static int
120
osmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param)
121
{
122
   /* no-op */
123
   return 0;
124
}
125
 
126
 
127
/**
128
 * Create/return singleton st_api object.
129
 */
130
static struct st_api *
131
get_st_api(void)
132
{
133
   static struct st_api *stapi = NULL;
134
   if (!stapi) {
135
      stapi = st_gl_api_create();
136
   }
137
   return stapi;
138
}
139
 
140
 
141
/**
142
 * Create/return a singleton st_manager object.
143
 */
144
static struct st_manager *
145
get_st_manager(void)
146
{
147
   static struct st_manager *stmgr = NULL;
148
   if (!stmgr) {
149
      stmgr = CALLOC_STRUCT(st_manager);
150
      if (stmgr) {
151
         stmgr->screen = osmesa_create_screen();
152
         stmgr->get_param = osmesa_st_get_param;
153
         stmgr->get_egl_image = NULL;
5063 serge 154
      }
4358 Serge 155
   }
156
   return stmgr;
157
}
158
 
159
 
160
static INLINE boolean
161
little_endian(void)
162
{
163
   const unsigned ui = 1;
164
   return *((const char *) &ui);
165
}
166
 
167
 
168
/**
169
 * Given an OSMESA_x format and a GL_y type, return the best
170
 * matching PIPE_FORMAT_z.
171
 * Note that we can't exactly match all user format/type combinations
172
 * with gallium formats.  If we find this to be a problem, we can
173
 * implement more elaborate format/type conversion in the flush_front()
174
 * function.
175
 */
176
static enum pipe_format
177
osmesa_choose_format(GLenum format, GLenum type)
178
{
179
   switch (format) {
180
   case OSMESA_RGBA:
181
      if (type == GL_UNSIGNED_BYTE) {
182
         if (little_endian())
183
            return PIPE_FORMAT_R8G8B8A8_UNORM;
184
         else
185
            return PIPE_FORMAT_A8B8G8R8_UNORM;
186
      }
187
      else if (type == GL_UNSIGNED_SHORT) {
188
         return PIPE_FORMAT_R16G16B16A16_UNORM;
189
      }
190
      else if (type == GL_FLOAT) {
191
         return PIPE_FORMAT_R32G32B32A32_FLOAT;
192
      }
193
      else {
194
         return PIPE_FORMAT_NONE;
195
      }
196
      break;
197
   case OSMESA_BGRA:
198
      if (type == GL_UNSIGNED_BYTE) {
199
         if (little_endian())
200
            return PIPE_FORMAT_B8G8R8A8_UNORM;
201
         else
202
            return PIPE_FORMAT_A8R8G8B8_UNORM;
203
      }
204
      else if (type == GL_UNSIGNED_SHORT) {
205
         return PIPE_FORMAT_R16G16B16A16_UNORM;
206
      }
207
      else if (type == GL_FLOAT) {
208
         return PIPE_FORMAT_R32G32B32A32_FLOAT;
209
      }
210
      else {
211
         return PIPE_FORMAT_NONE;
212
      }
213
      break;
214
   case OSMESA_ARGB:
215
      if (type == GL_UNSIGNED_BYTE) {
216
         if (little_endian())
217
            return PIPE_FORMAT_A8R8G8B8_UNORM;
218
         else
219
            return PIPE_FORMAT_B8G8R8A8_UNORM;
220
      }
221
      else if (type == GL_UNSIGNED_SHORT) {
222
         return PIPE_FORMAT_R16G16B16A16_UNORM;
223
      }
224
      else if (type == GL_FLOAT) {
225
         return PIPE_FORMAT_R32G32B32A32_FLOAT;
226
      }
227
      else {
228
         return PIPE_FORMAT_NONE;
229
      }
230
      break;
231
   case OSMESA_RGB:
232
      if (type == GL_UNSIGNED_BYTE) {
233
         return PIPE_FORMAT_R8G8B8_UNORM;
234
      }
235
      else if (type == GL_UNSIGNED_SHORT) {
236
         return PIPE_FORMAT_R16G16B16_UNORM;
237
      }
238
      else if (type == GL_FLOAT) {
239
         return PIPE_FORMAT_R32G32B32_FLOAT;
240
      }
241
      else {
242
         return PIPE_FORMAT_NONE;
243
      }
244
      break;
245
   case OSMESA_BGR:
246
      /* No gallium format for this one */
247
      return PIPE_FORMAT_NONE;
248
   case OSMESA_RGB_565:
249
      return PIPE_FORMAT_B5G6R5_UNORM;
250
   default:
251
      ; /* fall-through */
252
   }
253
   return PIPE_FORMAT_NONE;
254
}
255
 
256
 
257
/**
258
 * Initialize an st_visual object.
259
 */
260
static void
261
osmesa_init_st_visual(struct st_visual *vis,
262
                      enum pipe_format color_format,
263
                      enum pipe_format ds_format,
264
                      enum pipe_format accum_format)
265
{
266
   vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
267
   vis->color_format = color_format;
268
   vis->depth_stencil_format = ds_format;
269
   vis->accum_format = accum_format;
270
   vis->samples = 1;
271
   vis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
272
}
273
 
274
 
275
/**
276
 * Return the osmesa_buffer that corresponds to an st_framebuffer_iface.
277
 */
278
static INLINE struct osmesa_buffer *
279
stfbi_to_osbuffer(struct st_framebuffer_iface *stfbi)
280
{
281
   return (struct osmesa_buffer *) stfbi->st_manager_private;
282
}
283
 
284
 
285
/**
286
 * Called via glFlush/glFinish.  This is where we copy the contents
287
 * of the driver's color buffer into the user-specified buffer.
288
 */
289
static boolean
290
osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx,
291
                                  struct st_framebuffer_iface *stfbi,
292
                                  enum st_attachment_type statt)
293
{
294
   OSMesaContext osmesa = OSMesaGetCurrentContext();
295
   struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
296
   struct pipe_context *pipe = stctx->pipe;
297
   struct pipe_resource *res = osbuffer->textures[statt];
298
   struct pipe_transfer *transfer = NULL;
299
   struct pipe_box box;
300
   void *map;
301
   ubyte *src, *dst;
302
   unsigned y, bytes, bpp;
303
   int dst_stride;
304
 
305
   u_box_2d(0, 0, res->width0, res->height0, &box);
306
 
307
   map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box,
308
                            &transfer);
309
 
310
   /*
311
    * Copy the color buffer from the resource to the user's buffer.
312
    */
313
   bpp = util_format_get_blocksize(osbuffer->visual.color_format);
314
   src = map;
315
   dst = osbuffer->map;
316
   if (osmesa->user_row_length)
317
      dst_stride = bpp * osmesa->user_row_length;
318
   else
319
      dst_stride = bpp * osbuffer->width;
320
   bytes = bpp * res->width0;
321
 
322
   if (osmesa->y_up) {
323
      /* need to flip image upside down */
324
      dst = dst + (res->height0 - 1) * dst_stride;
325
      dst_stride = -dst_stride;
326
   }
327
 
328
   for (y = 0; y < res->height0; y++) {
329
      memcpy(dst, src, bytes);
330
      dst += dst_stride;
331
      src += transfer->stride;
332
   }
333
 
334
   pipe->transfer_unmap(pipe, transfer);
335
 
336
   return TRUE;
337
}
338
 
339
 
340
/**
341
 * Called by the st manager to validate the framebuffer (allocate
342
 * its resources).
343
 */
344
static boolean
345
osmesa_st_framebuffer_validate(struct st_context_iface *stctx,
346
                               struct st_framebuffer_iface *stfbi,
347
                               const enum st_attachment_type *statts,
348
                               unsigned count,
349
                               struct pipe_resource **out)
350
{
351
   struct pipe_screen *screen = get_st_manager()->screen;
352
   enum st_attachment_type i;
353
   struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
354
   struct pipe_resource templat;
355
 
356
   memset(&templat, 0, sizeof(templat));
357
   templat.target = PIPE_TEXTURE_RECT;
358
   templat.format = 0; /* setup below */
359
   templat.last_level = 0;
360
   templat.width0 = osbuffer->width;
361
   templat.height0 = osbuffer->height;
362
   templat.depth0 = 1;
363
   templat.array_size = 1;
364
   templat.usage = PIPE_USAGE_DEFAULT;
365
   templat.bind = 0; /* setup below */
366
   templat.flags = 0;
367
 
368
   for (i = 0; i < count; i++) {
369
      enum pipe_format format = PIPE_FORMAT_NONE;
370
      unsigned bind = 0;
371
 
372
      /*
373
       * At this time, we really only need to handle the front-left color
374
       * attachment, since that's all we specified for the visual in
375
       * osmesa_init_st_visual().
376
       */
377
      if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
378
         format = osbuffer->visual.color_format;
379
         bind = PIPE_BIND_RENDER_TARGET;
380
      }
381
      else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
382
         format = osbuffer->visual.depth_stencil_format;
383
         bind = PIPE_BIND_DEPTH_STENCIL;
384
      }
385
      else if (statts[i] == ST_ATTACHMENT_ACCUM) {
386
         format = osbuffer->visual.accum_format;
387
         bind = PIPE_BIND_RENDER_TARGET;
388
      }
389
      else {
390
         debug_warning("Unexpected attachment type in "
391
                       "osmesa_st_framebuffer_validate()");
392
      }
393
 
394
      templat.format = format;
395
      templat.bind = bind;
396
      out[i] = osbuffer->textures[i] =
397
         screen->resource_create(screen, &templat);
398
   }
399
 
400
   return TRUE;
401
}
402
 
403
 
404
static struct st_framebuffer_iface *
405
osmesa_create_st_framebuffer(void)
406
{
407
   struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface);
408
   if (stfbi) {
409
      stfbi->flush_front = osmesa_st_framebuffer_flush_front;
410
      stfbi->validate = osmesa_st_framebuffer_validate;
411
      p_atomic_set(&stfbi->stamp, 1);
412
   }
413
   return stfbi;
414
}
415
 
416
 
417
/**
418
 * Create new buffer and add to linked list.
419
 */
420
static struct osmesa_buffer *
421
osmesa_create_buffer(enum pipe_format color_format,
422
                     enum pipe_format ds_format,
423
                     enum pipe_format accum_format)
424
{
425
   struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer);
426
   if (osbuffer) {
427
      osbuffer->stfb = osmesa_create_st_framebuffer();
428
 
429
      osbuffer->stfb->st_manager_private = osbuffer;
430
      osbuffer->stfb->visual = &osbuffer->visual;
431
 
432
      osmesa_init_st_visual(&osbuffer->visual, color_format,
433
                            ds_format, accum_format);
434
 
435
      /* insert into linked list */
436
      osbuffer->next = BufferList;
437
      BufferList = osbuffer;
438
   }
439
 
440
   return osbuffer;
441
}
442
 
443
 
444
/**
445
 * Search linked list for a buffer with matching pixel formats.
446
 */
447
static struct osmesa_buffer *
448
osmesa_find_buffer(enum pipe_format color_format,
449
                   enum pipe_format ds_format,
450
                   enum pipe_format accum_format)
451
{
452
   struct osmesa_buffer *b;
453
 
454
   /* Check if we already have a suitable buffer for the given formats */
455
   for (b = BufferList; b; b = b->next) {
456
      if (b->visual.color_format == color_format &&
457
          b->visual.depth_stencil_format == ds_format &&
458
          b->visual.accum_format == accum_format) {
459
         return b;
460
      }
461
   }
462
   return NULL;
463
}
464
 
465
 
466
static void
467
osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
468
{
469
   FREE(osbuffer->stfb);
470
   FREE(osbuffer);
471
}
472
 
473
 
474
 
475
/**********************************************************************/
476
/*****                    Public Functions                        *****/
477
/**********************************************************************/
478
 
479
 
480
/**
481
 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
482
 * an RGBA vs Color-Index mode flag.
483
 *
484
 * Input:  format - Must be GL_RGBA
485
 *         sharelist - specifies another OSMesaContext with which to share
486
 *                     display lists.  NULL indicates no sharing.
487
 * Return:  an OSMesaContext or 0 if error
488
 */
489
GLAPI OSMesaContext GLAPIENTRY
490
OSMesaCreateContext(GLenum format, OSMesaContext sharelist)
491
{
492
   return OSMesaCreateContextExt(format, 24, 8, 0, sharelist);
493
}
494
 
495
 
496
/**
497
 * New in Mesa 3.5
498
 *
499
 * Create context and specify size of ancillary buffers.
500
 */
501
GLAPI OSMesaContext GLAPIENTRY
502
OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits,
503
                       GLint accumBits, OSMesaContext sharelist)
504
{
505
   OSMesaContext osmesa;
506
   struct st_context_iface *st_shared;
507
   enum st_context_error st_error = 0;
508
   struct st_context_attribs attribs;
509
   struct st_api *stapi = get_st_api();
510
 
511
   if (sharelist) {
512
      st_shared = sharelist->stctx;
513
   }
514
   else {
515
      st_shared = NULL;
516
   }
517
 
518
   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
519
   if (!osmesa)
520
      return NULL;
521
 
522
   /* Choose depth/stencil/accum buffer formats */
523
   if (accumBits > 0) {
524
      osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM;
525
   }
526
   if (depthBits > 0 && stencilBits > 0) {
527
      osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
528
   }
529
   else if (stencilBits > 0) {
530
      osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT;
531
   }
532
   else if (depthBits >= 24) {
533
      osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
534
   }
535
   else if (depthBits >= 16) {
536
      osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
537
   }
538
 
539
   /*
540
    * Create the rendering context
541
    */
542
   attribs.profile = ST_PROFILE_DEFAULT;
543
   attribs.major = 2;
544
   attribs.minor = 1;
545
   attribs.flags = 0;  /* ST_CONTEXT_FLAG_x */
546
   attribs.options.force_glsl_extensions_warn = FALSE;
547
   attribs.options.disable_blend_func_extended = FALSE;
548
   attribs.options.disable_glsl_line_continuations = FALSE;
549
   attribs.options.disable_shader_bit_encoding = FALSE;
550
   attribs.options.force_s3tc_enable = FALSE;
551
   attribs.options.force_glsl_version = 0;
552
 
553
   osmesa_init_st_visual(&attribs.visual,
554
                         PIPE_FORMAT_R8G8B8A8_UNORM,
555
                         osmesa->depth_stencil_format,
556
                         osmesa->accum_format);
557
 
558
   osmesa->stctx = stapi->create_context(stapi, get_st_manager(),
559
                                         &attribs, &st_error, st_shared);
560
   if (!osmesa->stctx) {
561
      FREE(osmesa);
562
      return NULL;
563
   }
564
 
565
   osmesa->stctx->st_manager_private = osmesa;
566
 
567
   osmesa->format = format;
568
   osmesa->user_row_length = 0;
569
   osmesa->y_up = GL_TRUE;
570
 
571
   return osmesa;
572
}
573
 
574
 
575
/**
576
 * Destroy an Off-Screen Mesa rendering context.
577
 *
578
 * \param osmesa  the context to destroy
579
 */
580
GLAPI void GLAPIENTRY
581
OSMesaDestroyContext(OSMesaContext osmesa)
582
{
583
   if (osmesa) {
584
      osmesa->stctx->destroy(osmesa->stctx);
585
      FREE(osmesa);
586
   }
587
}
588
 
589
 
590
/**
591
 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
592
 * block of memory which the client provides.  Its size must be at least
593
 * as large as width*height*pixelSize.  Its address should be a multiple
594
 * of 4 if using RGBA mode.
595
 *
596
 * By default, image data is stored in the order of glDrawPixels: row-major
597
 * order with the lower-left image pixel stored in the first array position
598
 * (ie. bottom-to-top).
599
 *
600
 * If the context's viewport hasn't been initialized yet, it will now be
601
 * initialized to (0,0,width,height).
602
 *
603
 * Input:  osmesa - the rendering context
604
 *         buffer - the image buffer memory
605
 *         type - data type for pixel components
606
 *                GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT
607
 *                or GL_FLOAT.
608
 *         width, height - size of image buffer in pixels, at least 1
609
 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
610
 *          invalid type, invalid size, etc.
611
 */
612
GLAPI GLboolean GLAPIENTRY
613
OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
614
                  GLsizei width, GLsizei height)
615
{
616
   struct st_api *stapi = get_st_api();
617
   struct osmesa_buffer *osbuffer;
618
   enum pipe_format color_format;
619
 
620
   if (!osmesa || !buffer || width < 1 || height < 1) {
621
      return GL_FALSE;
622
   }
623
 
624
   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
625
      return GL_FALSE;
626
   }
627
 
628
   color_format = osmesa_choose_format(osmesa->format, type);
629
   if (color_format == PIPE_FORMAT_NONE) {
630
      fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n");
631
      return GL_FALSE;
632
   }
633
 
634
   /* See if we already have a buffer that uses these pixel formats */
635
   osbuffer = osmesa_find_buffer(color_format,
636
                                 osmesa->depth_stencil_format,
637
                                 osmesa->accum_format);
638
   if (!osbuffer) {
639
      /* Existing buffer found, create new buffer */
640
      osbuffer = osmesa_create_buffer(color_format,
641
                                      osmesa->depth_stencil_format,
642
                                      osmesa->accum_format);
643
   }
644
 
645
   osbuffer->width = width;
646
   osbuffer->height = height;
647
   osbuffer->map = buffer;
648
 
649
   /* XXX unused for now */
650
   (void) osmesa_destroy_buffer;
651
 
652
   osmesa->current_buffer = osbuffer;
653
   osmesa->type = type;
654
 
655
   stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb);
656
 
657
   return GL_TRUE;
658
}
659
 
660
 
661
 
662
GLAPI OSMesaContext GLAPIENTRY
663
OSMesaGetCurrentContext(void)
664
{
665
   struct st_api *stapi = get_st_api();
666
   struct st_context_iface *st = stapi->get_current(stapi);
667
   return st ? (OSMesaContext) st->st_manager_private : NULL;
668
}
669
 
670
 
671
 
672
GLAPI void GLAPIENTRY
673
OSMesaPixelStore(GLint pname, GLint value)
674
{
675
   OSMesaContext osmesa = OSMesaGetCurrentContext();
676
 
677
   switch (pname) {
678
   case OSMESA_ROW_LENGTH:
679
      osmesa->user_row_length = value;
680
      break;
681
   case OSMESA_Y_UP:
682
      osmesa->y_up = value ? GL_TRUE : GL_FALSE;
683
      break;
684
   default:
685
      fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n");
686
      return;
687
   }
688
}
689
 
690
 
691
GLAPI void GLAPIENTRY
692
OSMesaGetIntegerv(GLint pname, GLint *value)
693
{
694
   OSMesaContext osmesa = OSMesaGetCurrentContext();
695
   struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL;
696
 
697
   switch (pname) {
698
   case OSMESA_WIDTH:
699
      *value = osbuffer ? osbuffer->width : 0;
700
      return;
701
   case OSMESA_HEIGHT:
702
      *value = osbuffer ? osbuffer->height : 0;
703
      return;
704
   case OSMESA_FORMAT:
705
      *value = osmesa->format;
706
      return;
707
   case OSMESA_TYPE:
708
      /* current color buffer's data type */
709
      *value = osmesa->type;
710
      return;
711
   case OSMESA_ROW_LENGTH:
712
      *value = osmesa->user_row_length;
713
      return;
714
   case OSMESA_Y_UP:
715
      *value = osmesa->y_up;
716
      return;
717
   case OSMESA_MAX_WIDTH:
718
      /* fall-through */
719
   case OSMESA_MAX_HEIGHT:
720
      {
721
         struct pipe_screen *screen = get_st_manager()->screen;
722
         int maxLevels = screen->get_param(screen,
723
                                           PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
724
         *value = 1 << (maxLevels - 1);
725
         *value = 8 * 1024;
726
      }
727
      return;
728
   default:
729
      fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n");
730
      return;
731
   }
732
}
733
 
734
 
735
/**
736
 * Return information about the depth buffer associated with an OSMesa context.
737
 * Input:  c - the OSMesa context
738
 * Output:  width, height - size of buffer in pixels
739
 *          bytesPerValue - bytes per depth value (2 or 4)
740
 *          buffer - pointer to depth buffer values
741
 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
742
 */
743
GLAPI GLboolean GLAPIENTRY
744
OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height,
745
                     GLint *bytesPerValue, void **buffer)
746
{
747
   struct osmesa_buffer *osbuffer = c->current_buffer;
748
   struct pipe_context *pipe = c->stctx->pipe;
749
   struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL];
750
   struct pipe_transfer *transfer = NULL;
751
   struct pipe_box box;
752
 
753
   /*
754
    * Note: we can't really implement this function with gallium as
755
    * we did for swrast.  We can't just map the resource and leave it
756
    * mapped (and there's no OSMesaUnmapDepthBuffer() function) so
757
    * we unmap the buffer here and return a 'stale' pointer.  This should
758
    * actually be OK in most cases where the caller of this function
759
    * immediately uses the pointer.
760
    */
761
 
762
   u_box_2d(0, 0, res->width0, res->height0, &box);
763
 
764
   *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box,
765
                                &transfer);
766
   if (!*buffer) {
767
      return GL_FALSE;
768
   }
769
 
770
   *width = res->width0;
771
   *height = res->height0;
772
   *bytesPerValue = util_format_get_blocksize(res->format);
773
 
774
   pipe->transfer_unmap(pipe, transfer);
775
 
776
   return GL_TRUE;
777
}
778
 
779
 
780
/**
781
 * Return the color buffer associated with an OSMesa context.
782
 * Input:  c - the OSMesa context
783
 * Output:  width, height - size of buffer in pixels
784
 *          format - the pixel format (OSMESA_FORMAT)
785
 *          buffer - pointer to color buffer values
786
 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
787
 */
788
GLAPI GLboolean GLAPIENTRY
789
OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width,
790
                      GLint *height, GLint *format, void **buffer)
791
{
792
   struct osmesa_buffer *osbuffer = osmesa->current_buffer;
793
 
794
   if (osbuffer) {
795
      *width = osbuffer->width;
796
      *height = osbuffer->height;
797
      *format = osmesa->format;
798
      *buffer = osbuffer->map;
799
      return GL_TRUE;
800
   }
801
   else {
802
      *width = 0;
803
      *height = 0;
804
      *format = 0;
805
      *buffer = 0;
806
      return GL_FALSE;
807
   }
808
}
809
 
810
 
811
struct name_function
812
{
813
   const char *Name;
814
   OSMESAproc Function;
815
};
816
 
817
static struct name_function functions[] = {
818
   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
819
   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
820
   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
821
   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
822
   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
823
   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
824
   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
825
   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
826
   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
827
   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
828
   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
829
   { NULL, NULL }
830
};
831
 
832
 
833
GLAPI OSMESAproc GLAPIENTRY
834
OSMesaGetProcAddress(const char *funcName)
835
{
836
   int i;
837
   for (i = 0; functions[i].Name; i++) {
838
      if (strcmp(functions[i].Name, funcName) == 0)
839
         return functions[i].Function;
840
   }
841
   return _glapi_get_proc_address(funcName);
842
}
843
 
844
 
845
GLAPI void GLAPIENTRY
846
OSMesaColorClamp(GLboolean enable)
847
{
848
   extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp);
849
 
850
   _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
851
                    enable ? GL_TRUE : GL_FIXED_ONLY_ARB);
852
}