]> git.cworth.org Git - apitrace/blob - retrace/glretrace_glx.cpp
stash: Trace and replay of glx-tfp works
[apitrace] / retrace / glretrace_glx.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include "glproc.hpp"
28 #include "retrace.hpp"
29 #include "glretrace.hpp"
30
31
32 #ifndef GLX_PBUFFER_HEIGHT
33 #define GLX_PBUFFER_HEIGHT 0x8040
34 #endif
35
36 #ifndef GLX_PBUFFER_WIDTH
37 #define GLX_PBUFFER_WIDTH 0x8041
38 #endif
39
40
41 using namespace glretrace;
42
43 typedef struct {
44     int width;
45     int height;
46     int depth;
47 } PixmapDesc;
48
49 typedef std::map<unsigned long, glws::Drawable *> DrawableMap;
50 typedef std::map<unsigned long long, Context *> ContextMap;
51 typedef std::map<unsigned long, PixmapDesc *> PixmapDescMap;
52 typedef std::map<GLXFBConfig, GLXFBConfig> ConfigMap;
53 static DrawableMap drawable_map;
54 static ContextMap context_map;
55 static PixmapDescMap pixmap_desc_map;
56 static ConfigMap config_map;
57
58 static glws::Drawable *
59 getDrawable(unsigned long drawable_id) {
60     if (drawable_id == 0) {
61         return NULL;
62     }
63
64     DrawableMap::const_iterator it;
65     it = drawable_map.find(drawable_id);
66     if (it == drawable_map.end()) {
67         return (drawable_map[drawable_id] = glretrace::createDrawable());
68     }
69
70     return it->second;
71 }
72
73 static Context *
74 getContext(unsigned long long context_ptr) {
75     if (context_ptr == 0) {
76         return NULL;
77     }
78
79     ContextMap::const_iterator it;
80     it = context_map.find(context_ptr);
81     if (it == context_map.end()) {
82         return (context_map[context_ptr] = glretrace::createContext());
83     }
84
85     return it->second;
86 }
87
88 static void retrace_glXCreateContext(trace::Call &call) {
89     unsigned long long orig_context = call.ret->toUIntPtr();
90     Context *share_context = getContext(call.arg(2).toUIntPtr());
91
92     Context *context = glretrace::createContext(share_context);
93     context_map[orig_context] = context;
94 }
95
96 static void retrace_glXCreateContextAttribsARB(trace::Call &call) {
97     unsigned long long orig_context = call.ret->toUIntPtr();
98     Context *share_context = getContext(call.arg(2).toUIntPtr());
99
100     Context *context = glretrace::createContext(share_context);
101     context_map[orig_context] = context;
102 }
103
104 static void retrace_glXMakeCurrent(trace::Call &call) {
105     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt());
106     Context *new_context = getContext(call.arg(2).toUIntPtr());
107
108     glretrace::makeCurrent(call, new_drawable, new_context);
109 }
110
111
112 static void retrace_glXDestroyContext(trace::Call &call) {
113     Context *context = getContext(call.arg(1).toUIntPtr());
114
115     if (!context) {
116         return;
117     }
118
119     delete context;
120 }
121
122 static void retrace_glXSwapBuffers(trace::Call &call) {
123     glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
124
125     frame_complete(call);
126     if (retrace::doubleBuffer) {
127         if (drawable) {
128             drawable->swapBuffers();
129         }
130     } else {
131         glFlush();
132     }
133 }
134
135 static void retrace_glXCreateNewContext(trace::Call &call) {
136     unsigned long long orig_context = call.ret->toUIntPtr();
137     Context *share_context = getContext(call.arg(3).toUIntPtr());
138
139     Context *context = glretrace::createContext(share_context);
140     context_map[orig_context] = context;
141 }
142
143 static void retrace_glXCreatePbuffer(trace::Call &call) {
144     const trace::Value *attrib_list = dynamic_cast<const trace::Array *>(&call.arg(2));
145     int width = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_WIDTH, 0);
146     int height = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_HEIGHT, 0);
147
148     unsigned long long orig_drawable = call.ret->toUInt();
149
150     glws::Drawable *drawable = glretrace::createPbuffer(width, height);
151     
152     drawable_map[orig_drawable] = drawable;
153 }
154
155 static void retrace_glXDestroyPbuffer(trace::Call &call) {
156     glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
157
158     if (!drawable) {
159         return;
160     }
161
162     delete drawable;
163 }
164
165 static void retrace_glXMakeContextCurrent(trace::Call &call) {
166     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt());
167     Context *new_context = getContext(call.arg(3).toUIntPtr());
168
169     glretrace::makeCurrent(call, new_drawable, new_context);
170 }
171
172 static void retrace_glXCreateWindow(trace::Call &call) {
173     glws::Drawable *window = getDrawable(call.arg(2).toUInt());
174
175     glretrace::createWindow(window);
176 }
177
178 static void retrace_glXDestroyWindow(trace::Call &call) {
179     glws::Drawable *window = getDrawable(call.arg(1).toUInt());
180
181     glretrace::destroyWindow(window);
182 }
183
184 static void retrace_XCreatePixmap(trace::Call &call) {
185     unsigned pixmap_id = call.ret->toUInt();
186
187     PixmapDesc *desc = new(PixmapDesc);
188
189     desc->width = call.arg(2).toUInt();
190     desc->height = call.arg(3).toUInt();
191     desc->depth = call.arg(4).toUInt();
192
193     pixmap_desc_map[pixmap_id] = desc;
194 }
195
196 static void retrace_XFreePixmap(trace::Call &call) {
197     unsigned pixmap_id = call.arg(1).toUInt();
198     PixmapDescMap::iterator it;
199
200     it = pixmap_desc_map.find(pixmap_id);
201     delete it->second;
202     pixmap_desc_map.erase(it);
203 }
204
205 static void retrace_glXCreatePixmap(trace::Call &call) {
206     retrace::ScopedAllocator _allocator;
207     GLXFBConfig fbconfig, orig_fbconfig = (GLXFBConfig) call.arg(1).toPointer();
208     unsigned orig_pixmap = call.arg(2).toUInt();
209     unsigned orig_gl_pixmap = call.ret->toUInt();
210     PixmapDesc *desc = pixmap_desc_map[orig_pixmap];
211     glws::Drawable *pixmap, *gl_pixmap;
212
213     int *attrib_list;
214     attrib_list = static_cast<int *>(_allocator.alloc(&call.arg(3), sizeof *attrib_list));
215     if (attrib_list) {
216         const trace::Array *arg_list = dynamic_cast<const trace::Array *>(&call.arg(3));
217         for (size_t i = 0; i < arg_list->values.size(); i++) {
218             attrib_list[i] = (*arg_list->values[i]).toSInt();
219         }
220     }
221
222     printf("Looking for %p in FB-config map\n", orig_fbconfig);
223     fbconfig = config_map[orig_fbconfig];
224
225     pixmap = glretrace::createPixmap(desc->width, desc->height, desc->depth);
226
227     gl_pixmap = glretrace::createGLPixmap(fbconfig, pixmap, desc->width, desc->height, attrib_list);
228
229     drawable_map[orig_pixmap] = pixmap;
230     drawable_map[orig_gl_pixmap] = gl_pixmap;
231 }
232
233 static void retrace_glXBindTexImageEXT(trace::Call &call) {
234     glws::Drawable *pixmap = getDrawable(call.arg(1).toUInt());
235
236     glretrace::bindTexImage(pixmap, call.arg(2).toSInt());
237 }
238
239 static void retrace_glXReleaseTexImageEXT(trace::Call &call) {
240     glws::Drawable *pixmap = getDrawable(call.arg(1).toUInt());
241
242     glretrace::releaseTexImage(pixmap, call.arg(2).toSInt());
243 }
244
245 static void retrace_glXCopySubBufferMESA(trace::Call &call) {
246     glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
247     int x, y, width, height;
248
249     x = call.arg(2).toSInt();
250     y = call.arg(3).toSInt();
251     width = call.arg(4).toSInt();
252     height = call.arg(5).toSInt();
253
254     glretrace::copySubBuffer(drawable, x, y, width, height);
255 }
256
257 static void retrace_PutImageData(trace::Call &call) {
258     glws::Drawable *drawable = getDrawable(call.arg(0).toUInt());
259     int width, height, depth, bits_per_pixel, bytes_per_line, byte_order;
260     char *data;
261
262     data = static_cast<char *>((call.arg(1)).toPointer());
263     width = call.arg(2).toSInt();
264     height = call.arg(3).toSInt();
265     depth = call.arg(4).toSInt();
266     bits_per_pixel = call.arg(5).toSInt();
267     bytes_per_line = call.arg(6).toSInt();
268     byte_order = call.arg(7).toSInt();
269
270     glretrace::putImageData(drawable, data, width, height, depth,
271                             bits_per_pixel, bytes_per_line, byte_order);
272 }
273
274 static void retrace_glXChooseFBConfig(trace::Call &call) {
275     retrace::ScopedAllocator _allocator;
276     int orig_nelements;
277     const trace::Array *orig_configs;
278     GLXFBConfig config;
279
280     int *attrib_list;
281     attrib_list = static_cast<int *>(_allocator.alloc(&call.arg(2), sizeof *attrib_list));
282     if (attrib_list) {
283         const trace::Array *arg_list = dynamic_cast<const trace::Array *>(&call.arg(2));
284         for (size_t i = 0; i < arg_list->values.size(); i++) {
285             attrib_list[i] = arg_list->values[i]->toSInt();
286         }
287     }   
288
289     orig_nelements = dynamic_cast<const trace::Array *>(&call.arg(3))->values[0]->toSInt();
290     orig_configs = dynamic_cast<const trace::Array *>(call.ret);
291
292     config = glretrace::chooseConfig(attrib_list);
293     for (size_t i = 0; i < orig_nelements; i++) {
294         printf("Mapping FB config %p to %p\n", orig_configs->values[i]->toPointer(), config);
295         config_map[static_cast<GLXFBConfig>(orig_configs->values[i]->toPointer())] = config;
296     }
297 }
298
299 const retrace::Entry glretrace::glx_callbacks[] = {
300     //{"glXBindChannelToWindowSGIX", &retrace_glXBindChannelToWindowSGIX},
301     //{"glXBindSwapBarrierNV", &retrace_glXBindSwapBarrierNV},
302     //{"glXBindSwapBarrierSGIX", &retrace_glXBindSwapBarrierSGIX},
303     {"glXBindTexImageEXT", &retrace_glXBindTexImageEXT},
304     //{"glXChannelRectSGIX", &retrace_glXChannelRectSGIX},
305     //{"glXChannelRectSyncSGIX", &retrace_glXChannelRectSyncSGIX},
306     {"glXChooseFBConfig", &retrace_glXChooseFBConfig},
307     {"glXChooseFBConfigSGIX", &retrace::ignore},
308     {"glXChooseVisual", &retrace::ignore},
309     //{"glXCopyContext", &retrace_glXCopyContext},
310     //{"glXCopyImageSubDataNV", &retrace_glXCopyImageSubDataNV},
311     {"glXCopySubBufferMESA", &retrace_glXCopySubBufferMESA},
312     {"glXCreateContextAttribsARB", &retrace_glXCreateContextAttribsARB},
313     {"glXCreateContext", &retrace_glXCreateContext},
314     //{"glXCreateContextWithConfigSGIX", &retrace_glXCreateContextWithConfigSGIX},
315     //{"glXCreateGLXPbufferSGIX", &retrace_glXCreateGLXPbufferSGIX},
316     //{"glXCreateGLXPixmap", &retrace_glXCreateGLXPixmap},
317     //{"glXCreateGLXPixmapWithConfigSGIX", &retrace_glXCreateGLXPixmapWithConfigSGIX},
318     {"glXCreateNewContext", &retrace_glXCreateNewContext},
319     {"glXCreatePbuffer", &retrace_glXCreatePbuffer},
320     {"glXCreatePixmap", &retrace_glXCreatePixmap},
321     {"XCreatePixmap", &retrace_XCreatePixmap},
322     {"XFreePixmap", &retrace_XFreePixmap},
323     {"PutImageData", &retrace_PutImageData},
324     {"glXCreateWindow", &retrace_glXCreateWindow},
325     //{"glXCushionSGI", &retrace_glXCushionSGI},
326     {"glXDestroyContext", &retrace_glXDestroyContext},
327     //{"glXDestroyGLXPbufferSGIX", &retrace_glXDestroyGLXPbufferSGIX},
328     //{"glXDestroyGLXPixmap", &retrace_glXDestroyGLXPixmap},
329     {"glXDestroyPbuffer", &retrace_glXDestroyPbuffer},
330     //{"glXDestroyPixmap", &retrace_glXDestroyPixmap},
331     {"glXDestroyWindow", &retrace_glXDestroyWindow},
332     //{"glXFreeContextEXT", &retrace_glXFreeContextEXT},
333     {"glXGetAGPOffsetMESA", &retrace::ignore},
334     {"glXGetClientString", &retrace::ignore},
335     {"glXGetConfig", &retrace::ignore},
336     {"glXGetContextIDEXT", &retrace::ignore},
337     {"glXGetCurrentContext", &retrace::ignore},
338     {"glXGetCurrentDisplayEXT", &retrace::ignore},
339     {"glXGetCurrentDisplay", &retrace::ignore},
340     {"glXGetCurrentDrawable", &retrace::ignore},
341     {"glXGetCurrentReadDrawable", &retrace::ignore},
342     {"glXGetCurrentReadDrawableSGI", &retrace::ignore},
343     {"glXGetFBConfigAttrib", &retrace::ignore},
344     {"glXGetFBConfigAttribSGIX", &retrace::ignore},
345     {"glXGetFBConfigFromVisualSGIX", &retrace::ignore},
346     {"glXGetFBConfigs", &retrace::ignore},
347     {"glXGetMscRateOML", &retrace::ignore},
348     {"glXGetProcAddressARB", &retrace::ignore},
349     {"glXGetProcAddress", &retrace::ignore},
350     {"glXGetSelectedEvent", &retrace::ignore},
351     {"glXGetSelectedEventSGIX", &retrace::ignore},
352     {"glXGetSwapIntervalMESA", &retrace::ignore},
353     {"glXGetSyncValuesOML", &retrace::ignore},
354     {"glXGetVideoSyncSGI", &retrace::ignore},
355     {"glXGetVisualFromFBConfig", &retrace::ignore},
356     {"glXGetVisualFromFBConfigSGIX", &retrace::ignore},
357     //{"glXImportContextEXT", &retrace_glXImportContextEXT},
358     {"glXIsDirect", &retrace::ignore},
359     //{"glXJoinSwapGroupNV", &retrace_glXJoinSwapGroupNV},
360     //{"glXJoinSwapGroupSGIX", &retrace_glXJoinSwapGroupSGIX},
361     {"glXMakeContextCurrent", &retrace_glXMakeContextCurrent},
362     //{"glXMakeCurrentReadSGI", &retrace_glXMakeCurrentReadSGI},
363     {"glXMakeCurrent", &retrace_glXMakeCurrent},
364     {"glXQueryChannelDeltasSGIX", &retrace::ignore},
365     {"glXQueryChannelRectSGIX", &retrace::ignore},
366     {"glXQueryContextInfoEXT", &retrace::ignore},
367     {"glXQueryContext", &retrace::ignore},
368     {"glXQueryDrawable", &retrace::ignore},
369     {"glXQueryExtension", &retrace::ignore},
370     {"glXQueryExtensionsString", &retrace::ignore},
371     {"glXQueryFrameCountNV", &retrace::ignore},
372     {"glXQueryGLXPbufferSGIX", &retrace::ignore},
373     {"glXQueryMaxSwapBarriersSGIX", &retrace::ignore},
374     {"glXQueryMaxSwapGroupsNV", &retrace::ignore},
375     {"glXQueryServerString", &retrace::ignore},
376     {"glXQuerySwapGroupNV", &retrace::ignore},
377     {"glXQueryVersion", &retrace::ignore},
378     //{"glXReleaseBuffersMESA", &retrace_glXReleaseBuffersMESA},
379     {"glXReleaseTexImageEXT", &retrace_glXReleaseTexImageEXT},
380     //{"glXResetFrameCountNV", &retrace_glXResetFrameCountNV},
381     //{"glXSelectEvent", &retrace_glXSelectEvent},
382     //{"glXSelectEventSGIX", &retrace_glXSelectEventSGIX},
383     //{"glXSet3DfxModeMESA", &retrace_glXSet3DfxModeMESA},
384     //{"glXSwapBuffersMscOML", &retrace_glXSwapBuffersMscOML},
385     {"glXSwapBuffers", &retrace_glXSwapBuffers},
386     {"glXSwapIntervalEXT", &retrace::ignore},
387     {"glXSwapIntervalSGI", &retrace::ignore},
388     //{"glXUseXFont", &retrace_glXUseXFont},
389     {"glXWaitForMscOML", &retrace::ignore},
390     {"glXWaitForSbcOML", &retrace::ignore},
391     {"glXWaitGL", &retrace::ignore},
392     {"glXWaitVideoSyncSGI", &retrace::ignore},
393     {"glXWaitX", &retrace::ignore},
394     {NULL, NULL},
395 };
396