Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  7.9
4
 *
5
 * Copyright (C) 2010 LunarG Inc.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
 * DEALINGS IN THE SOFTWARE.
24
 *
25
 * Authors:
26
 *    Chia-I Wu 
27
 */
28
 
29
#include "state_tracker/st_gl_api.h"
30
 
31
#include "pipe/p_context.h"
32
#include "pipe/p_screen.h"
33
#include "util/u_format.h"
34
#include "util/u_pointer.h"
35
#include "util/u_inlines.h"
36
#include "util/u_atomic.h"
37
#include "util/u_surface.h"
38
 
39
#include "main/mtypes.h"
40
#include "main/context.h"
41
#include "main/texobj.h"
42
#include "main/teximage.h"
43
#include "main/texstate.h"
44
#include "main/framebuffer.h"
45
#include "main/fbobject.h"
46
#include "main/renderbuffer.h"
47
#include "main/version.h"
48
#include "st_texture.h"
49
 
50
#include "st_context.h"
51
#include "st_format.h"
52
#include "st_cb_fbo.h"
53
#include "st_cb_flush.h"
54
#include "st_manager.h"
55
 
56
/**
57
 * Cast wrapper to convert a struct gl_framebuffer to an st_framebuffer.
58
 * Return NULL if the struct gl_framebuffer is a user-created framebuffer.
59
 * We'll only return non-null for window system framebuffers.
60
 * Note that this function may fail.
61
 */
62
static INLINE struct st_framebuffer *
63
st_ws_framebuffer(struct gl_framebuffer *fb)
64
{
65
   /* FBO cannot be casted.  See st_new_framebuffer */
66
   return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL);
67
}
68
 
69
/**
70
 * Map an attachment to a buffer index.
71
 */
72
static INLINE gl_buffer_index
73
attachment_to_buffer_index(enum st_attachment_type statt)
74
{
75
   gl_buffer_index index;
76
 
77
   switch (statt) {
78
   case ST_ATTACHMENT_FRONT_LEFT:
79
      index = BUFFER_FRONT_LEFT;
80
      break;
81
   case ST_ATTACHMENT_BACK_LEFT:
82
      index = BUFFER_BACK_LEFT;
83
      break;
84
   case ST_ATTACHMENT_FRONT_RIGHT:
85
      index = BUFFER_FRONT_RIGHT;
86
      break;
87
   case ST_ATTACHMENT_BACK_RIGHT:
88
      index = BUFFER_BACK_RIGHT;
89
      break;
90
   case ST_ATTACHMENT_DEPTH_STENCIL:
91
      index = BUFFER_DEPTH;
92
      break;
93
   case ST_ATTACHMENT_ACCUM:
94
      index = BUFFER_ACCUM;
95
      break;
96
   case ST_ATTACHMENT_SAMPLE:
97
   default:
98
      index = BUFFER_COUNT;
99
      break;
100
   }
101
 
102
   return index;
103
}
104
 
105
/**
106
 * Map a buffer index to an attachment.
107
 */
108
static INLINE enum st_attachment_type
109
buffer_index_to_attachment(gl_buffer_index index)
110
{
111
   enum st_attachment_type statt;
112
 
113
   switch (index) {
114
   case BUFFER_FRONT_LEFT:
115
      statt = ST_ATTACHMENT_FRONT_LEFT;
116
      break;
117
   case BUFFER_BACK_LEFT:
118
      statt = ST_ATTACHMENT_BACK_LEFT;
119
      break;
120
   case BUFFER_FRONT_RIGHT:
121
      statt = ST_ATTACHMENT_FRONT_RIGHT;
122
      break;
123
   case BUFFER_BACK_RIGHT:
124
      statt = ST_ATTACHMENT_BACK_RIGHT;
125
      break;
126
   case BUFFER_DEPTH:
127
      statt = ST_ATTACHMENT_DEPTH_STENCIL;
128
      break;
129
   case BUFFER_ACCUM:
130
      statt = ST_ATTACHMENT_ACCUM;
131
      break;
132
   default:
133
      statt = ST_ATTACHMENT_INVALID;
134
      break;
135
   }
136
 
137
   return statt;
138
}
139
 
140
/**
141
 * Validate a framebuffer to make sure up-to-date pipe_textures are used.
142
 */
143
static void
144
st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
145
{
146
   struct pipe_context *pipe = st->pipe;
147
   struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
148
   uint width, height;
149
   unsigned i;
150
   boolean changed = FALSE;
151
 
152
   if (!p_atomic_read(&stfb->revalidate))
153
      return;
154
 
155
   /* validate the fb */
156
   if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
157
      return;
158
 
159
   width = stfb->Base.Width;
160
   height = stfb->Base.Height;
161
 
162
   for (i = 0; i < stfb->num_statts; i++) {
163
      struct st_renderbuffer *strb;
164
      struct pipe_surface *ps, surf_tmpl;
165
      gl_buffer_index idx;
166
 
167
      if (!textures[i])
168
         continue;
169
 
170
      idx = attachment_to_buffer_index(stfb->statts[i]);
171
      if (idx >= BUFFER_COUNT) {
172
         pipe_resource_reference(&textures[i], NULL);
173
         continue;
174
      }
175
 
176
      strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
177
      assert(strb);
178
      if (strb->texture == textures[i]) {
179
         pipe_resource_reference(&textures[i], NULL);
180
         continue;
181
      }
182
 
183
      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
184
      u_surface_default_template(&surf_tmpl, textures[i],
185
                                 PIPE_BIND_RENDER_TARGET);
186
      ps = pipe->create_surface(pipe, textures[i], &surf_tmpl);
187
      if (ps) {
188
         pipe_surface_reference(&strb->surface, ps);
189
         pipe_resource_reference(&strb->texture, ps->texture);
190
         /* ownership transfered */
191
         pipe_surface_reference(&ps, NULL);
192
 
193
         changed = TRUE;
194
 
195
         strb->Base.Width = strb->surface->width;
196
         strb->Base.Height = strb->surface->height;
197
 
198
         width = strb->Base.Width;
199
         height = strb->Base.Height;
200
      }
201
 
202
      pipe_resource_reference(&textures[i], NULL);
203
   }
204
 
205
   if (changed) {
206
      st->dirty.st |= ST_NEW_FRAMEBUFFER;
207
      _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
208
 
209
      assert(stfb->Base.Width == width);
210
      assert(stfb->Base.Height == height);
211
   }
212
 
213
   p_atomic_set(&stfb->revalidate, FALSE);
214
}
215
 
216
/**
217
 * Update the attachments to validate by looping the existing renderbuffers.
218
 */
219
static void
220
st_framebuffer_update_attachments(struct st_framebuffer *stfb)
221
{
222
   gl_buffer_index idx;
223
 
224
   stfb->num_statts = 0;
225
   for (idx = 0; idx < BUFFER_COUNT; idx++) {
226
      struct st_renderbuffer *strb;
227
      enum st_attachment_type statt;
228
 
229
      strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
230
      if (!strb || strb->software)
231
         continue;
232
 
233
      statt = buffer_index_to_attachment(idx);
234
      if (statt != ST_ATTACHMENT_INVALID &&
235
          st_visual_have_buffers(stfb->iface->visual, 1 << statt))
236
         stfb->statts[stfb->num_statts++] = statt;
237
   }
238
 
239
   p_atomic_set(&stfb->revalidate, TRUE);
240
}
241
 
242
/**
243
 * Add a renderbuffer to the framebuffer.
244
 */
245
static boolean
246
st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
247
                                gl_buffer_index idx)
248
{
249
   struct gl_renderbuffer *rb;
250
   enum pipe_format format;
251
   int samples;
252
   boolean sw;
253
 
254
   if (!stfb->iface)
255
      return FALSE;
256
 
257
   /* do not distinguish depth/stencil buffers */
258
   if (idx == BUFFER_STENCIL)
259
      idx = BUFFER_DEPTH;
260
 
261
   switch (idx) {
262
   case BUFFER_DEPTH:
263
      format = stfb->iface->visual->depth_stencil_format;
264
      sw = FALSE;
265
      break;
266
   case BUFFER_ACCUM:
267
      format = stfb->iface->visual->accum_format;
268
      sw = TRUE;
269
      break;
270
   default:
271
      format = stfb->iface->visual->color_format;
272
      sw = FALSE;
273
      break;
274
   }
275
 
276
   if (format == PIPE_FORMAT_NONE)
277
      return FALSE;
278
 
279
   samples = stfb->iface->visual->samples;
280
   if (!samples)
281
      samples = st_get_msaa();
282
 
283
   rb = st_new_renderbuffer_fb(format, samples, sw);
284
   if (!rb)
285
      return FALSE;
286
 
287
   if (idx != BUFFER_DEPTH) {
288
      _mesa_add_renderbuffer(&stfb->Base, idx, rb);
289
   }
290
   else {
291
      if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0))
292
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb);
293
      if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1))
294
         _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb);
295
   }
296
 
297
   return TRUE;
298
}
299
 
300
/**
301
 * Intialize a struct gl_config from a visual.
302
 */
303
static void
304
st_visual_to_context_mode(const struct st_visual *visual,
305
                          struct gl_config *mode)
306
{
307
   memset(mode, 0, sizeof(*mode));
308
 
309
   if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
310
      mode->doubleBufferMode = GL_TRUE;
311
   if (st_visual_have_buffers(visual,
312
            ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
313
      mode->stereoMode = GL_TRUE;
314
 
315
   if (visual->color_format != PIPE_FORMAT_NONE) {
316
      mode->rgbMode = GL_TRUE;
317
 
318
      mode->redBits =
319
         util_format_get_component_bits(visual->color_format,
320
               UTIL_FORMAT_COLORSPACE_RGB, 0);
321
      mode->greenBits =
322
         util_format_get_component_bits(visual->color_format,
323
               UTIL_FORMAT_COLORSPACE_RGB, 1);
324
      mode->blueBits =
325
         util_format_get_component_bits(visual->color_format,
326
               UTIL_FORMAT_COLORSPACE_RGB, 2);
327
      mode->alphaBits =
328
         util_format_get_component_bits(visual->color_format,
329
               UTIL_FORMAT_COLORSPACE_RGB, 3);
330
 
331
      mode->rgbBits = mode->redBits +
332
         mode->greenBits + mode->blueBits + mode->alphaBits;
333
   }
334
 
335
   if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
336
      mode->depthBits =
337
         util_format_get_component_bits(visual->depth_stencil_format,
338
               UTIL_FORMAT_COLORSPACE_ZS, 0);
339
      mode->stencilBits =
340
         util_format_get_component_bits(visual->depth_stencil_format,
341
               UTIL_FORMAT_COLORSPACE_ZS, 1);
342
 
343
      mode->haveDepthBuffer = mode->depthBits > 0;
344
      mode->haveStencilBuffer = mode->stencilBits > 0;
345
   }
346
 
347
   if (visual->accum_format != PIPE_FORMAT_NONE) {
348
      mode->haveAccumBuffer = GL_TRUE;
349
 
350
      mode->accumRedBits =
351
         util_format_get_component_bits(visual->accum_format,
352
               UTIL_FORMAT_COLORSPACE_RGB, 0);
353
      mode->accumGreenBits =
354
         util_format_get_component_bits(visual->accum_format,
355
               UTIL_FORMAT_COLORSPACE_RGB, 1);
356
      mode->accumBlueBits =
357
         util_format_get_component_bits(visual->accum_format,
358
               UTIL_FORMAT_COLORSPACE_RGB, 2);
359
      mode->accumAlphaBits =
360
         util_format_get_component_bits(visual->accum_format,
361
               UTIL_FORMAT_COLORSPACE_RGB, 3);
362
   }
363
 
364
   if (visual->samples) {
365
      mode->sampleBuffers = 1;
366
      mode->samples = visual->samples;
367
   }
368
}
369
 
370
/**
371
 * Determine the default draw or read buffer from a visual.
372
 */
373
static void
374
st_visual_to_default_buffer(const struct st_visual *visual,
375
                            GLenum *buffer, GLint *index)
376
{
377
   enum st_attachment_type statt;
378
   GLenum buf;
379
   gl_buffer_index idx;
380
 
381
   statt = visual->render_buffer;
382
   /* do nothing if an invalid render buffer is specified */
383
   if (statt == ST_ATTACHMENT_INVALID ||
384
       !st_visual_have_buffers(visual, 1 << statt))
385
      return;
386
 
387
   switch (statt) {
388
   case ST_ATTACHMENT_FRONT_LEFT:
389
      buf = GL_FRONT_LEFT;
390
      idx = BUFFER_FRONT_LEFT;
391
      break;
392
   case ST_ATTACHMENT_BACK_LEFT:
393
      buf = GL_BACK_LEFT;
394
      idx = BUFFER_BACK_LEFT;
395
      break;
396
   case ST_ATTACHMENT_FRONT_RIGHT:
397
      buf = GL_FRONT_RIGHT;
398
      idx = BUFFER_FRONT_RIGHT;
399
      break;
400
   case ST_ATTACHMENT_BACK_RIGHT:
401
      buf = GL_BACK_RIGHT;
402
      idx = BUFFER_BACK_RIGHT;
403
      break;
404
   default:
405
      buf = GL_NONE;
406
      idx = BUFFER_COUNT;
407
      break;
408
   }
409
 
410
   if (buf != GL_NONE) {
411
      if (buffer)
412
         *buffer = buf;
413
      if (index)
414
         *index = idx;
415
   }
416
}
417
 
418
/**
419
 * Create a framebuffer from a manager interface.
420
 */
421
static struct st_framebuffer *
422
st_framebuffer_create(struct st_framebuffer_iface *stfbi)
423
{
424
   struct st_framebuffer *stfb;
425
   struct gl_config mode;
426
   gl_buffer_index idx;
427
 
428
   stfb = CALLOC_STRUCT(st_framebuffer);
429
   if (!stfb)
430
      return NULL;
431
 
432
   /* for FBO-only context */
433
   if (!stfbi) {
434
      struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer();
435
 
436
      stfb->Base = *base;
437
 
438
      return stfb;
439
   }
440
 
441
   st_visual_to_context_mode(stfbi->visual, &mode);
442
   _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
443
 
444
   /* modify the draw/read buffers of the fb */
445
   st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0],
446
         &stfb->Base._ColorDrawBufferIndexes[0]);
447
   st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer,
448
         &stfb->Base._ColorReadBufferIndex);
449
 
450
   stfb->iface = stfbi;
451
 
452
   /* add the color buffer */
453
   idx = stfb->Base._ColorDrawBufferIndexes[0];
454
   if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
455
      FREE(stfb);
456
      return NULL;
457
   }
458
 
459
   st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
460
   st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
461
 
462
   st_framebuffer_update_attachments(stfb);
463
 
464
   stfb->Base.Initialized = GL_TRUE;
465
 
466
   return stfb;
467
}
468
 
469
/**
470
 * Reference a framebuffer.
471
 */
472
static void
473
st_framebuffer_reference(struct st_framebuffer **ptr,
474
                         struct st_framebuffer *stfb)
475
{
476
   struct gl_framebuffer *fb = &stfb->Base;
477
   _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
478
}
479
 
480
static void
481
st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
482
                                      struct st_framebuffer_iface *stfbi)
483
{
484
   struct st_context *st = (struct st_context *) stctxi;
485
   struct st_framebuffer *stfb;
486
 
487
   /* either draw or read winsys fb */
488
   stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
489
   if (!stfb || stfb->iface != stfbi)
490
      stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
491
 
492
   if (stfb && stfb->iface == stfbi) {
493
      p_atomic_set(&stfb->revalidate, TRUE);
494
   }
495
   else {
496
      /* This function is probably getting called when we've detected a
497
       * change in a window's size but the currently bound context is
498
       * not bound to that window.
499
       * If the st_framebuffer_iface structure had a pointer to the
500
       * corresponding st_framebuffer we'd be able to handle this.
501
       */
502
   }
503
}
504
 
505
static void
506
st_context_flush(struct st_context_iface *stctxi, unsigned flags,
507
                 struct pipe_fence_handle **fence)
508
{
509
   struct st_context *st = (struct st_context *) stctxi;
510
   st_flush(st, flags, fence);
511
   if (flags & PIPE_FLUSH_RENDER_CACHE)
512
      st_manager_flush_frontbuffer(st);
513
}
514
 
515
static boolean
516
st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
517
                    int level, enum pipe_format internal_format,
518
                    struct pipe_resource *tex, boolean mipmap)
519
{
520
   struct st_context *st = (struct st_context *) stctxi;
521
   struct gl_context *ctx = st->ctx;
522
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
523
   struct gl_texture_object *texObj;
524
   struct gl_texture_image *texImage;
525
   struct st_texture_object *stObj;
526
   struct st_texture_image *stImage;
527
   GLenum internalFormat;
528
   GLuint width, height, depth;
529
 
530
   switch (target) {
531
   case ST_TEXTURE_1D:
532
      target = GL_TEXTURE_1D;
533
      break;
534
   case ST_TEXTURE_2D:
535
      target = GL_TEXTURE_2D;
536
      break;
537
   case ST_TEXTURE_3D:
538
      target = GL_TEXTURE_3D;
539
      break;
540
   case ST_TEXTURE_RECT:
541
      target = GL_TEXTURE_RECTANGLE_ARB;
542
      break;
543
   default:
544
      return FALSE;
545
      break;
546
   }
547
 
548
   texObj = _mesa_select_tex_object(ctx, texUnit, target);
549
   _mesa_lock_texture(ctx, texObj);
550
 
551
   stObj = st_texture_object(texObj);
552
   /* switch to surface based */
553
   if (!stObj->surface_based) {
554
      _mesa_clear_texture_object(ctx, texObj);
555
      stObj->surface_based = GL_TRUE;
556
   }
557
 
558
   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
559
   stImage = st_texture_image(texImage);
560
   if (tex) {
561
      gl_format texFormat;
562
 
563
      /*
564
       * XXX When internal_format and tex->format differ, st_finalize_texture
565
       * needs to allocate a new texture with internal_format and copy the
566
       * texture here into the new one.  It will result in surface_copy being
567
       * called on surfaces whose formats differ.
568
       *
569
       * To avoid that, internal_format is (wrongly) ignored here.  A sane fix
570
       * is to use a sampler view.
571
       */
572
      if (!st_sampler_compat_formats(tex->format, internal_format))
573
	 internal_format = tex->format;
574
 
575
      if (util_format_get_component_bits(internal_format,
576
               UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
577
         internalFormat = GL_RGBA;
578
      else
579
         internalFormat = GL_RGB;
580
 
581
      texFormat = st_ChooseTextureFormat(ctx, internalFormat,
582
                                         GL_RGBA, GL_UNSIGNED_BYTE);
583
 
584
      _mesa_init_teximage_fields(ctx, target, texImage,
585
                                 tex->width0, tex->height0, 1, 0,
586
                                 internalFormat, texFormat);
587
 
588
      width = tex->width0;
589
      height = tex->height0;
590
      depth = tex->depth0;
591
 
592
      /* grow the image size until we hit level = 0 */
593
      while (level > 0) {
594
         if (width != 1)
595
            width <<= 1;
596
         if (height != 1)
597
            height <<= 1;
598
         if (depth != 1)
599
            depth <<= 1;
600
         level--;
601
      }
602
   }
603
   else {
604
      _mesa_clear_texture_image(ctx, texImage);
605
      width = height = depth = 0;
606
   }
607
 
608
   pipe_resource_reference(&stImage->pt, tex);
609
   stObj->width0 = width;
610
   stObj->height0 = height;
611
   stObj->depth0 = depth;
612
 
613
   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
614
   _mesa_unlock_texture(ctx, texObj);
615
 
616
   return TRUE;
617
}
618
 
619
static void
620
st_context_copy(struct st_context_iface *stctxi,
621
                struct st_context_iface *stsrci, unsigned mask)
622
{
623
   struct st_context *st = (struct st_context *) stctxi;
624
   struct st_context *src = (struct st_context *) stsrci;
625
 
626
   _mesa_copy_context(src->ctx, st->ctx, mask);
627
}
628
 
629
static boolean
630
st_context_share(struct st_context_iface *stctxi,
631
                 struct st_context_iface *stsrci)
632
{
633
   struct st_context *st = (struct st_context *) stctxi;
634
   struct st_context *src = (struct st_context *) stsrci;
635
 
636
   return _mesa_share_state(st->ctx, src->ctx);
637
}
638
 
639
static void
640
st_context_destroy(struct st_context_iface *stctxi)
641
{
642
   struct st_context *st = (struct st_context *) stctxi;
643
   st_destroy_context(st);
644
}
645
 
646
static struct st_context_iface *
647
st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
648
                      const struct st_context_attribs *attribs,
649
                      struct st_context_iface *shared_stctxi)
650
{
651
   struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
652
   struct st_context *st;
653
   struct pipe_context *pipe;
654
   struct gl_config mode;
655
   gl_api api;
656
 
657
   if (!(stapi->profile_mask & (1 << attribs->profile)))
658
      return NULL;
659
 
660
   switch (attribs->profile) {
661
   case ST_PROFILE_DEFAULT:
662
      api = API_OPENGL;
663
      break;
664
   case ST_PROFILE_OPENGL_ES1:
665
      api = API_OPENGLES;
666
      break;
667
   case ST_PROFILE_OPENGL_ES2:
668
      api = API_OPENGLES2;
669
      break;
670
   case ST_PROFILE_OPENGL_CORE:
671
   default:
672
      return NULL;
673
      break;
674
   }
675
 
676
   pipe = smapi->screen->context_create(smapi->screen, NULL);
677
   if (!pipe)
678
      return NULL;
679
 
680
   st_visual_to_context_mode(&attribs->visual, &mode);
681
   st = st_create_context(api, pipe, &mode, shared_ctx);
682
   if (!st) {
683
      pipe->destroy(pipe);
684
      return NULL;
685
   }
686
 
687
   /* need to perform version check */
688
   if (attribs->major > 1 || attribs->minor > 0) {
689
      _mesa_compute_version(st->ctx);
690
 
691
      if (st->ctx->VersionMajor < attribs->major ||
692
          st->ctx->VersionMajor < attribs->minor) {
693
         st_destroy_context(st);
694
         return NULL;
695
      }
696
   }
697
 
698
   st->invalidate_on_gl_viewport =
699
      smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
700
 
701
   st->iface.destroy = st_context_destroy;
702
   st->iface.notify_invalid_framebuffer =
703
      st_context_notify_invalid_framebuffer;
704
   st->iface.flush = st_context_flush;
705
   st->iface.teximage = st_context_teximage;
706
   st->iface.copy = st_context_copy;
707
   st->iface.share = st_context_share;
708
   st->iface.st_context_private = (void *) smapi;
709
 
710
   return &st->iface;
711
}
712
 
713
static boolean
714
st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
715
                    struct st_framebuffer_iface *stdrawi,
716
                    struct st_framebuffer_iface *streadi)
717
{
718
   struct st_context *st = (struct st_context *) stctxi;
719
   struct st_framebuffer *stdraw, *stread, *stfb;
720
   boolean ret;
721
 
722
   _glapi_check_multithread();
723
 
724
   if (st) {
725
      /* reuse/create the draw fb */
726
      stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
727
      if (stfb && stfb->iface == stdrawi) {
728
         stdraw = NULL;
729
         st_framebuffer_reference(&stdraw, stfb);
730
      }
731
      else {
732
         stdraw = st_framebuffer_create(stdrawi);
733
      }
734
 
735
      /* reuse/create the read fb */
736
      stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
737
      if (!stfb || stfb->iface != streadi)
738
         stfb = stdraw;
739
      if (stfb && stfb->iface == streadi) {
740
         stread = NULL;
741
         st_framebuffer_reference(&stread, stfb);
742
      }
743
      else {
744
         stread = st_framebuffer_create(streadi);
745
      }
746
 
747
      if (stdraw && stread) {
748
         st_framebuffer_validate(stdraw, st);
749
         if (stread != stdraw)
750
            st_framebuffer_validate(stread, st);
751
 
752
         /* modify the draw/read buffers of the context */
753
         if (stdraw->iface) {
754
            st_visual_to_default_buffer(stdraw->iface->visual,
755
                  &st->ctx->Color.DrawBuffer[0], NULL);
756
         }
757
         if (stread->iface) {
758
            st_visual_to_default_buffer(stread->iface->visual,
759
                  &st->ctx->Pixel.ReadBuffer, NULL);
760
         }
761
 
762
         ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
763
      }
764
      else {
765
         ret = FALSE;
766
      }
767
 
768
      st_framebuffer_reference(&stdraw, NULL);
769
      st_framebuffer_reference(&stread, NULL);
770
   }
771
   else {
772
      ret = _mesa_make_current(NULL, NULL, NULL);
773
   }
774
 
775
   return ret;
776
}
777
 
778
static struct st_context_iface *
779
st_api_get_current(struct st_api *stapi)
780
{
781
   GET_CURRENT_CONTEXT(ctx);
782
   struct st_context *st = (ctx) ? ctx->st : NULL;
783
 
784
   return (st) ? &st->iface : NULL;
785
}
786
 
787
static st_proc_t
788
st_api_get_proc_address(struct st_api *stapi, const char *procname)
789
{
790
   return (st_proc_t) _glapi_get_proc_address(procname);
791
}
792
 
793
static void
794
st_api_destroy(struct st_api *stapi)
795
{
796
}
797
 
798
/**
799
 * Flush the front buffer if the current context renders to the front buffer.
800
 */
801
void
802
st_manager_flush_frontbuffer(struct st_context *st)
803
{
804
   struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer);
805
   struct st_renderbuffer *strb = NULL;
806
 
807
   if (stfb)
808
      strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
809
   if (!strb)
810
      return;
811
 
812
   /* never a dummy fb */
813
   assert(stfb->iface);
814
   stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
815
}
816
 
817
/**
818
 * Return the surface of an EGLImage.
819
 * FIXME: I think this should operate on resources, not surfaces
820
 */
821
struct pipe_surface *
822
st_manager_get_egl_image_surface(struct st_context *st,
823
                                 void *eglimg, unsigned usage)
824
{
825
   struct st_manager *smapi =
826
      (struct st_manager *) st->iface.st_context_private;
827
   struct st_egl_image stimg;
828
   struct pipe_surface *ps, surf_tmpl;
829
 
830
   if (!smapi || !smapi->get_egl_image)
831
      return NULL;
832
 
833
   memset(&stimg, 0, sizeof(stimg));
834
   if (!smapi->get_egl_image(smapi, eglimg, &stimg))
835
      return NULL;
836
 
837
   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
838
   surf_tmpl.format = stimg.texture->format;
839
   surf_tmpl.usage = usage;
840
   surf_tmpl.u.tex.level = stimg.level;
841
   surf_tmpl.u.tex.first_layer = stimg.layer;
842
   surf_tmpl.u.tex.last_layer = stimg.layer;
843
   ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl);
844
   pipe_resource_reference(&stimg.texture, NULL);
845
 
846
   return ps;
847
}
848
 
849
/**
850
 * Re-validate the framebuffers.
851
 */
852
void
853
st_manager_validate_framebuffers(struct st_context *st)
854
{
855
   struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
856
   struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer);
857
 
858
   if (stdraw)
859
      st_framebuffer_validate(stdraw, st);
860
   if (stread && stread != stdraw)
861
      st_framebuffer_validate(stread, st);
862
}
863
 
864
/**
865
 * Add a color renderbuffer on demand.
866
 */
867
boolean
868
st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb,
869
                                  gl_buffer_index idx)
870
{
871
   struct st_framebuffer *stfb = st_ws_framebuffer(fb);
872
 
873
   /* FBO */
874
   if (!stfb)
875
      return FALSE;
876
 
877
   if (stfb->Base.Attachment[idx].Renderbuffer)
878
      return TRUE;
879
 
880
   switch (idx) {
881
   case BUFFER_FRONT_LEFT:
882
   case BUFFER_BACK_LEFT:
883
   case BUFFER_FRONT_RIGHT:
884
   case BUFFER_BACK_RIGHT:
885
      break;
886
   default:
887
      return FALSE;
888
      break;
889
   }
890
 
891
   if (!st_framebuffer_add_renderbuffer(stfb, idx))
892
      return FALSE;
893
 
894
   st_framebuffer_update_attachments(stfb);
895
   st_invalidate_state(st->ctx, _NEW_BUFFERS);
896
 
897
   return TRUE;
898
}
899
 
900
static const struct st_api st_gl_api = {
901
   "Mesa " MESA_VERSION_STRING,
902
   ST_API_OPENGL,
903
#if FEATURE_GL
904
   ST_PROFILE_DEFAULT_MASK |
905
#endif
906
#if FEATURE_ES1
907
   ST_PROFILE_OPENGL_ES1_MASK |
908
#endif
909
#if FEATURE_ES2
910
   ST_PROFILE_OPENGL_ES2_MASK |
911
#endif
912
   0,
913
   st_api_destroy,
914
   st_api_get_proc_address,
915
   st_api_create_context,
916
   st_api_make_current,
917
   st_api_get_current,
918
};
919
 
920
struct st_api *
921
st_gl_api_create(void)
922
{
923
   return (struct st_api *) &st_gl_api;
924
}