]> git.cworth.org Git - apitrace/blob - retrace/glretrace_main.cpp
Share more code between glretrace and d3dretrace.
[apitrace] / retrace / glretrace_main.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 <string.h>
28
29 #include "retrace.hpp"
30 #include "glproc.hpp"
31 #include "glstate.hpp"
32 #include "glretrace.hpp"
33
34
35 namespace glretrace {
36
37 bool insideGlBeginEnd = false;
38 glws::Profile defaultProfile = glws::PROFILE_COMPAT;
39 glws::Visual *visual[glws::PROFILE_MAX];
40 glws::Drawable *drawable = NULL;
41 glws::Context *context = NULL;
42
43 void
44 checkGlError(trace::Call &call) {
45     GLenum error = glGetError();
46     if (error == GL_NO_ERROR) {
47         return;
48     }
49
50     std::ostream & os = retrace::warning(call);
51
52     os << "glGetError(";
53     os << call.name();
54     os << ") = ";
55
56     switch (error) {
57     case GL_INVALID_ENUM:
58         os << "GL_INVALID_ENUM";
59         break;
60     case GL_INVALID_VALUE:
61         os << "GL_INVALID_VALUE";
62         break;
63     case GL_INVALID_OPERATION:
64         os << "GL_INVALID_OPERATION";
65         break;
66     case GL_STACK_OVERFLOW:
67         os << "GL_STACK_OVERFLOW";
68         break;
69     case GL_STACK_UNDERFLOW:
70         os << "GL_STACK_UNDERFLOW";
71         break;
72     case GL_OUT_OF_MEMORY:
73         os << "GL_OUT_OF_MEMORY";
74         break;
75     case GL_INVALID_FRAMEBUFFER_OPERATION:
76         os << "GL_INVALID_FRAMEBUFFER_OPERATION";
77         break;
78     case GL_TABLE_TOO_LARGE:
79         os << "GL_TABLE_TOO_LARGE";
80         break;
81     default:
82         os << error;
83         break;
84     }
85     os << "\n";
86 }
87
88 /**
89  * Grow the current drawble.
90  *
91  * We need to infer the drawable size from GL calls because the drawable sizes
92  * are specified by OS specific calls which we do not trace.
93  */
94 void
95 updateDrawable(int width, int height) {
96     if (!drawable) {
97         return;
98     }
99
100     if (drawable->visible &&
101         width  <= drawable->width &&
102         height <= drawable->height) {
103         return;
104     }
105
106     // Ignore zero area viewports
107     if (width == 0 || height == 0) {
108         return;
109     }
110
111     // Check for bound framebuffer last, as this may have a performance impact.
112     GLint draw_framebuffer = 0;
113     glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
114     if (draw_framebuffer != 0) {
115         return;
116     }
117
118     drawable->resize(width, height);
119     drawable->show();
120
121     glScissor(0, 0, width, height);
122 }
123
124
125 void frame_complete(trace::Call &call) {
126     retrace::frameComplete(call);
127
128     if (!drawable) {
129         return;
130     }
131
132     if (!drawable->visible) {
133         retrace::warning(call) << "could not infer drawable size (glViewport never called)\n";
134     }
135 }
136
137
138 } /* namespace glretrace */
139
140
141 void
142 retrace::setUp(void) {
143     if (retrace::coreProfile) {
144         glretrace::defaultProfile = glws::PROFILE_CORE;
145     }
146
147     glws::init();
148
149     glretrace::visual[glws::PROFILE_COMPAT] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_COMPAT);
150     glretrace::visual[glws::PROFILE_CORE] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_CORE);
151     glretrace::visual[glws::PROFILE_ES1] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_ES1);
152     glretrace::visual[glws::PROFILE_ES2] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_ES2);
153 }
154
155
156 void
157 retrace::addCallbacks(retrace::Retracer &retracer)
158 {
159     retracer.addCallbacks(glretrace::gl_callbacks);
160     retracer.addCallbacks(glretrace::glx_callbacks);
161     retracer.addCallbacks(glretrace::wgl_callbacks);
162     retracer.addCallbacks(glretrace::cgl_callbacks);
163     retracer.addCallbacks(glretrace::egl_callbacks);
164 }
165
166
167 image::Image *
168 retrace::getSnapshot(void) {
169     if (!glretrace::drawable) {
170         return NULL;
171     }
172
173     return glstate::getDrawBufferImage();
174 }
175
176
177 bool
178 retrace::dumpState(std::ostream &os)
179 {
180     if (glretrace::insideGlBeginEnd ||
181         !glretrace::drawable ||
182         !glretrace::context) {
183         return false;
184     }
185
186     glstate::dumpCurrentContext(os);
187
188     return true;
189 }
190
191 void
192 retrace::flushRendering(void) {
193     glFlush();
194 }
195
196 void
197 retrace::waitForInput(void) {
198     while (glws::processEvents()) {
199     }
200 }
201
202 void
203 retrace::cleanUp(void) {
204     for (int n = 0; n < glws::PROFILE_MAX; n++) {
205         delete glretrace::visual[n];
206     }
207
208     glws::cleanup();
209 }