Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2010 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Soft-
6
 * ware"), to deal in the Software without restriction, including without
7
 * limitation the rights to use, copy, modify, merge, publish, distribute,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, provided that the above copyright
10
 * notice(s) and this permission notice appear in all copies of the Soft-
11
 * ware and that both the above copyright notice(s) and this permission
12
 * notice appear in supporting documentation.
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 MERCHANTABIL-
16
 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17
 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18
 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19
 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22
 * MANCE OF THIS SOFTWARE.
23
 *
24
 * Except as contained in this notice, the name of a copyright holder shall
25
 * not be used in advertising or otherwise to promote the sale, use or
26
 * other dealings in this Software without prior written authorization of
27
 * the copyright holder.
28
 *
29
 * Authors:
30
 *   Kristian Høgsberg (krh@bitplanet.net)
31
 */
32
 
33
#include "glapi.h"
34
#include "glxclient.h"
35
 
36
#ifndef GLX_USE_APPLEGL
37
 
38
extern struct _glapi_table *__glXNewIndirectAPI(void);
39
 
40
/*
41
** All indirect rendering contexts will share the same indirect dispatch table.
42
*/
43
static struct _glapi_table *IndirectAPI = NULL;
44
 
45
static void
46
indirect_destroy_context(struct glx_context *gc)
47
{
48
   __glXFreeVertexArrayState(gc);
49
 
50
   free((char *) gc->vendor);
51
   free((char *) gc->renderer);
52
   free((char *) gc->version);
53
   free((char *) gc->extensions);
54
   __glFreeAttributeState(gc);
55
   free((char *) gc->buf);
56
   free((char *) gc->client_state_private);
57
   free((char *) gc);
58
}
59
 
60
static Bool
61
SendMakeCurrentRequest(Display * dpy, CARD8 opcode,
62
                       GLXContextID gc_id, GLXContextTag gc_tag,
63
                       GLXDrawable draw, GLXDrawable read,
64
                       GLXContextTag *out_tag)
65
{
66
   xGLXMakeCurrentReply reply;
67
   Bool ret;
68
 
69
   LockDisplay(dpy);
70
 
71
   if (draw == read) {
72
      xGLXMakeCurrentReq *req;
73
 
74
      GetReq(GLXMakeCurrent, req);
75
      req->reqType = opcode;
76
      req->glxCode = X_GLXMakeCurrent;
77
      req->drawable = draw;
78
      req->context = gc_id;
79
      req->oldContextTag = gc_tag;
80
   }
81
   else {
82
      struct glx_display *priv = __glXInitialize(dpy);
83
 
84
      /* If the server can support the GLX 1.3 version, we should
85
       * perfer that.  Not only that, some servers support GLX 1.3 but
86
       * not the SGI extension.
87
       */
88
 
89
      if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
90
         xGLXMakeContextCurrentReq *req;
91
 
92
         GetReq(GLXMakeContextCurrent, req);
93
         req->reqType = opcode;
94
         req->glxCode = X_GLXMakeContextCurrent;
95
         req->drawable = draw;
96
         req->readdrawable = read;
97
         req->context = gc_id;
98
         req->oldContextTag = gc_tag;
99
      }
100
      else {
101
         xGLXVendorPrivateWithReplyReq *vpreq;
102
         xGLXMakeCurrentReadSGIReq *req;
103
 
104
         GetReqExtra(GLXVendorPrivateWithReply,
105
                     sz_xGLXMakeCurrentReadSGIReq -
106
                     sz_xGLXVendorPrivateWithReplyReq, vpreq);
107
         req = (xGLXMakeCurrentReadSGIReq *) vpreq;
108
         req->reqType = opcode;
109
         req->glxCode = X_GLXVendorPrivateWithReply;
110
         req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
111
         req->drawable = draw;
112
         req->readable = read;
113
         req->context = gc_id;
114
         req->oldContextTag = gc_tag;
115
      }
116
   }
117
 
118
   ret = _XReply(dpy, (xReply *) &reply, 0, False);
119
 
120
   if (out_tag)
121
      *out_tag = reply.contextTag;
122
 
123
   UnlockDisplay(dpy);
124
   SyncHandle();
125
 
126
   return ret;
127
}
128
 
129
static int
130
indirect_bind_context(struct glx_context *gc, struct glx_context *old,
131
		      GLXDrawable draw, GLXDrawable read)
132
{
133
   GLXContextTag tag;
134
   __GLXattribute *state;
135
   Display *dpy = gc->psc->dpy;
136
   int opcode = __glXSetupForCommand(dpy);
137
   Bool sent;
138
 
139
   if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {
140
      tag = old->currentContextTag;
141
      old->currentContextTag = 0;
142
   } else {
143
      tag = 0;
144
   }
145
 
146
   sent = SendMakeCurrentRequest(dpy, opcode, gc->xid, tag, draw, read,
147
				 &gc->currentContextTag);
148
 
149
   if (!IndirectAPI)
150
      IndirectAPI = __glXNewIndirectAPI();
151
   _glapi_set_dispatch(IndirectAPI);
152
 
153
   state = gc->client_state_private;
154
   if (state->array_state == NULL) {
155
      glGetString(GL_EXTENSIONS);
156
      glGetString(GL_VERSION);
157
      __glXInitVertexArrayState(gc);
158
   }
159
 
160
   return !sent;
161
}
162
 
163
static void
164
indirect_unbind_context(struct glx_context *gc, struct glx_context *new)
165
{
166
   Display *dpy = gc->psc->dpy;
167
   int opcode = __glXSetupForCommand(dpy);
168
 
169
   if (gc == new)
170
      return;
171
 
172
   /* We are either switching to no context, away from a indirect
173
    * context to a direct context or from one dpy to another and have
174
    * to send a request to the dpy to unbind the previous context.
175
    */
176
   if (!new || new->isDirect || new->psc->dpy != dpy) {
177
      SendMakeCurrentRequest(dpy, opcode, None,
178
			     gc->currentContextTag, None, None, NULL);
179
      gc->currentContextTag = 0;
180
   }
181
}
182
 
183
static void
184
indirect_wait_gl(struct glx_context *gc)
185
{
186
   xGLXWaitGLReq *req;
187
   Display *dpy = gc->currentDpy;
188
 
189
   /* Flush any pending commands out */
190
   __glXFlushRenderBuffer(gc, gc->pc);
191
 
192
   /* Send the glXWaitGL request */
193
   LockDisplay(dpy);
194
   GetReq(GLXWaitGL, req);
195
   req->reqType = gc->majorOpcode;
196
   req->glxCode = X_GLXWaitGL;
197
   req->contextTag = gc->currentContextTag;
198
   UnlockDisplay(dpy);
199
   SyncHandle();
200
}
201
 
202
static void
203
indirect_wait_x(struct glx_context *gc)
204
{
205
   xGLXWaitXReq *req;
206
   Display *dpy = gc->currentDpy;
207
 
208
   /* Flush any pending commands out */
209
   __glXFlushRenderBuffer(gc, gc->pc);
210
 
211
   LockDisplay(dpy);
212
   GetReq(GLXWaitX, req);
213
   req->reqType = gc->majorOpcode;
214
   req->glxCode = X_GLXWaitX;
215
   req->contextTag = gc->currentContextTag;
216
   UnlockDisplay(dpy);
217
   SyncHandle();
218
}
219
 
220
static void
221
indirect_use_x_font(struct glx_context *gc,
222
		    Font font, int first, int count, int listBase)
223
{
224
   xGLXUseXFontReq *req;
225
   Display *dpy = gc->currentDpy;
226
 
227
   /* Flush any pending commands out */
228
   __glXFlushRenderBuffer(gc, gc->pc);
229
 
230
   /* Send the glXUseFont request */
231
   LockDisplay(dpy);
232
   GetReq(GLXUseXFont, req);
233
   req->reqType = gc->majorOpcode;
234
   req->glxCode = X_GLXUseXFont;
235
   req->contextTag = gc->currentContextTag;
236
   req->font = font;
237
   req->first = first;
238
   req->count = count;
239
   req->listBase = listBase;
240
   UnlockDisplay(dpy);
241
   SyncHandle();
242
}
243
 
244
static void
245
indirect_bind_tex_image(Display * dpy,
246
			GLXDrawable drawable,
247
			int buffer, const int *attrib_list)
248
{
249
   xGLXVendorPrivateReq *req;
250
   struct glx_context *gc = __glXGetCurrentContext();
251
   CARD32 *drawable_ptr;
252
   INT32 *buffer_ptr;
253
   CARD32 *num_attrib_ptr;
254
   CARD32 *attrib_ptr;
255
   CARD8 opcode;
256
   unsigned int i;
257
 
258
   i = 0;
259
   if (attrib_list) {
260
      while (attrib_list[i * 2] != None)
261
         i++;
262
   }
263
 
264
   opcode = __glXSetupForCommand(dpy);
265
   if (!opcode)
266
      return;
267
 
268
   LockDisplay(dpy);
269
   GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
270
   req->reqType = opcode;
271
   req->glxCode = X_GLXVendorPrivate;
272
   req->vendorCode = X_GLXvop_BindTexImageEXT;
273
   req->contextTag = gc->currentContextTag;
274
 
275
   drawable_ptr = (CARD32 *) (req + 1);
276
   buffer_ptr = (INT32 *) (drawable_ptr + 1);
277
   num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
278
   attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
279
 
280
   *drawable_ptr = drawable;
281
   *buffer_ptr = buffer;
282
   *num_attrib_ptr = (CARD32) i;
283
 
284
   i = 0;
285
   if (attrib_list) {
286
      while (attrib_list[i * 2] != None) {
287
         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
288
         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
289
         i++;
290
      }
291
   }
292
 
293
   UnlockDisplay(dpy);
294
   SyncHandle();
295
}
296
 
297
static void
298
indirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
299
{
300
   xGLXVendorPrivateReq *req;
301
   struct glx_context *gc = __glXGetCurrentContext();
302
   CARD32 *drawable_ptr;
303
   INT32 *buffer_ptr;
304
   CARD8 opcode;
305
 
306
   opcode = __glXSetupForCommand(dpy);
307
   if (!opcode)
308
      return;
309
 
310
   LockDisplay(dpy);
311
   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
312
   req->reqType = opcode;
313
   req->glxCode = X_GLXVendorPrivate;
314
   req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
315
   req->contextTag = gc->currentContextTag;
316
 
317
   drawable_ptr = (CARD32 *) (req + 1);
318
   buffer_ptr = (INT32 *) (drawable_ptr + 1);
319
 
320
   *drawable_ptr = drawable;
321
   *buffer_ptr = buffer;
322
 
323
   UnlockDisplay(dpy);
324
   SyncHandle();
325
}
326
 
327
static const struct glx_context_vtable indirect_context_vtable = {
328
   .destroy             = indirect_destroy_context,
329
   .bind                = indirect_bind_context,
330
   .unbind              = indirect_unbind_context,
331
   .wait_gl             = indirect_wait_gl,
332
   .wait_x              = indirect_wait_x,
333
   .use_x_font          = indirect_use_x_font,
334
   .bind_tex_image      = indirect_bind_tex_image,
335
   .release_tex_image   = indirect_release_tex_image,
336
   .get_proc_address    = NULL,
337
};
338
 
339
/**
340
 * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
341
 * function called \c __glXAllocateClientState that allocates the memory and
342
 * does all the initialization (including the pixel pack / unpack).
343
 *
344
 * \note
345
 * This function is \b not the place to validate the context creation
346
 * parameters.  It is just the allocator for the \c glx_context.
347
 */
348
_X_HIDDEN struct glx_context *
349
indirect_create_context(struct glx_screen *psc,
350
			struct glx_config *mode,
351
			struct glx_context *shareList, int renderType)
352
{
353
   struct glx_context *gc;
354
   int bufSize;
355
   CARD8 opcode;
356
   __GLXattribute *state;
357
 
358
   opcode = __glXSetupForCommand(psc->dpy);
359
   if (!opcode) {
360
      return NULL;
361
   }
362
 
363
   /* Allocate our context record */
364
   gc = calloc(1, sizeof *gc);
365
   if (!gc) {
366
      /* Out of memory */
367
      return NULL;
368
   }
369
 
370
   glx_context_init(gc, psc, mode);
371
   gc->isDirect = GL_FALSE;
372
   gc->vtable = &indirect_context_vtable;
373
   state = calloc(1, sizeof(struct __GLXattributeRec));
374
   gc->renderType = renderType;
375
 
376
   if (state == NULL) {
377
      /* Out of memory */
378
      free(gc);
379
      return NULL;
380
   }
381
   gc->client_state_private = state;
382
   state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
383
 
384
   /*
385
    ** Create a temporary buffer to hold GLX rendering commands.  The size
386
    ** of the buffer is selected so that the maximum number of GLX rendering
387
    ** commands can fit in a single X packet and still have room in the X
388
    ** packet for the GLXRenderReq header.
389
    */
390
 
391
   bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
392
   gc->buf = malloc(bufSize);
393
   if (!gc->buf) {
394
      free(gc->client_state_private);
395
      free(gc);
396
      return NULL;
397
   }
398
   gc->bufSize = bufSize;
399
 
400
   /* Fill in the new context */
401
   gc->renderMode = GL_RENDER;
402
 
403
   state->storePack.alignment = 4;
404
   state->storeUnpack.alignment = 4;
405
 
406
   gc->attributes.stackPointer = &gc->attributes.stack[0];
407
 
408
   /*
409
    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
410
    */
411
   gc->fillImage = __glFillImage;
412
   gc->pc = gc->buf;
413
   gc->bufEnd = gc->buf + bufSize;
414
   gc->isDirect = GL_FALSE;
415
   if (__glXDebug) {
416
      /*
417
       ** Set limit register so that there will be one command per packet
418
       */
419
      gc->limit = gc->buf;
420
   }
421
   else {
422
      gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
423
   }
424
   gc->majorOpcode = opcode;
425
 
426
   /*
427
    ** Constrain the maximum drawing command size allowed to be
428
    ** transfered using the X_GLXRender protocol request.  First
429
    ** constrain by a software limit, then constrain by the protocl
430
    ** limit.
431
    */
432
   if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
433
      bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
434
   }
435
   if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
436
      bufSize = __GLX_MAX_RENDER_CMD_SIZE;
437
   }
438
   gc->maxSmallRenderCommandSize = bufSize;
439
 
440
 
441
   return gc;
442
}
443
 
444
_X_HIDDEN struct glx_context *
445
indirect_create_context_attribs(struct glx_screen *base,
446
				struct glx_config *config_base,
447
				struct glx_context *shareList,
448
				unsigned num_attribs,
449
				const uint32_t *attribs,
450
				unsigned *error)
451
{
452
   int renderType = GLX_RGBA_TYPE;
453
   unsigned i;
454
 
455
   /* The error parameter is only used on the server so that correct GLX
456
    * protocol errors can be generated.  On the client, it can be ignored.
457
    */
458
   (void) error;
459
 
460
   /* All of the attribute validation for indirect contexts is handled on the
461
    * server, so there's not much to do here. Still, we need to parse the
462
    * attributes to correctly set renderType.
463
    */
464
   for (i = 0; i < num_attribs; i++) {
465
      if (attribs[i * 2] == GLX_RENDER_TYPE)
466
         renderType = attribs[i * 2 + 1];
467
   }
468
 
469
   return indirect_create_context(base, config_base, shareList, renderType);
470
}
471
 
472
static const struct glx_screen_vtable indirect_screen_vtable = {
473
   .create_context         = indirect_create_context,
474
   .create_context_attribs = indirect_create_context_attribs,
475
   .query_renderer_integer = NULL,
476
   .query_renderer_string  = NULL,
477
};
478
 
479
_X_HIDDEN struct glx_screen *
480
indirect_create_screen(int screen, struct glx_display * priv)
481
{
482
   struct glx_screen *psc;
483
 
484
   psc = calloc(1, sizeof *psc);
485
   if (psc == NULL)
486
      return NULL;
487
 
488
   glx_screen_init(psc, screen, priv);
489
   psc->vtable = &indirect_screen_vtable;
490
 
491
   return psc;
492
}
493
 
494
#endif