BGE Rasterizer Cleanup: Removing KX_BlenderGL since it was mostly one-line functions...
[blender.git] / source / gameengine / BlenderRoutines / KX_BlenderCanvas.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
29  *  \ingroup blroutines
30  */
31
32 #include <GL/glew.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "KX_BlenderCanvas.h"
37
38 #include "DNA_image_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_screen_types.h"
41 #include "DNA_windowmanager_types.h"
42
43 #include "BKE_image.h"
44 #include "BKE_global.h"
45 #include "BKE_main.h"
46
47 #include "BLI_path_util.h"
48 #include "BLI_string.h"
49
50 #include <assert.h>
51
52 extern "C" {
53 #include "IMB_imbuf.h"
54 #include "IMB_imbuf_types.h"
55 #include "WM_api.h"
56 #include "wm_cursors.h"
57 #include "wm_window.h"
58 }
59
60 KX_BlenderCanvas::KX_BlenderCanvas(wmWindowManager *wm, wmWindow *win, RAS_Rect &rect, struct ARegion *ar) :
61 m_wm(wm),
62 m_win(win),
63 m_frame_rect(rect)
64 {
65         // initialize area so that it's available for game logic on frame 1 (ImageViewport)
66         m_area_rect = rect;
67         // area boundaries needed for mouse coordinates in Letterbox framing mode
68         m_area_left = ar->winrct.xmin;
69         m_area_top = ar->winrct.ymax;
70
71         glGetIntegerv(GL_VIEWPORT, (GLint *)m_viewport);
72 }
73
74 KX_BlenderCanvas::~KX_BlenderCanvas()
75 {
76 }
77
78 void KX_BlenderCanvas::Init()
79 {
80         glDepthFunc(GL_LEQUAL);
81 }
82
83
84 void KX_BlenderCanvas::SwapBuffers()
85 {
86         wm_window_swap_buffers(m_win);
87 }
88
89 void KX_BlenderCanvas::SetSwapInterval(int interval)
90 {
91         wm_window_set_swap_interval(m_win, interval);
92 }
93
94 int     KX_BlenderCanvas::GetSwapInterval()
95 {
96         return wm_window_get_swap_interval(m_win);
97 }
98
99 void KX_BlenderCanvas::ResizeWindow(int width, int height)
100 {
101         // Not implemented for the embedded player
102 }
103
104 void KX_BlenderCanvas::SetFullScreen(bool enable)
105 {
106         // Not implemented for the embedded player
107 }
108
109 bool KX_BlenderCanvas::GetFullScreen()
110 {
111         // Not implemented for the embedded player
112         return false;
113 }
114
115 bool KX_BlenderCanvas::BeginDraw()
116 {
117         // in case of multi-window we need to ensure we are drawing to the correct
118         // window always, because it may change in window event handling
119         wm_window_make_drawable(m_wm, m_win);
120         return true;
121 }
122
123
124 void KX_BlenderCanvas::EndDraw()
125 {
126         // nothing needs to be done here
127 }
128
129 void KX_BlenderCanvas::BeginFrame()
130 {
131         glEnable(GL_DEPTH_TEST);
132         glDepthFunc(GL_LEQUAL);
133 }
134
135
136 void KX_BlenderCanvas::EndFrame()
137 {
138         glDisable(GL_FOG);
139 }
140
141
142
143 void KX_BlenderCanvas::ClearColor(float r,float g,float b,float a)
144 {
145         glClearColor(r,g,b,a);
146 }
147
148
149
150 void KX_BlenderCanvas::ClearBuffer(int type)
151 {
152         int ogltype = 0;
153
154         if (type & RAS_ICanvas::COLOR_BUFFER )
155                 ogltype |= GL_COLOR_BUFFER_BIT;
156
157         if (type & RAS_ICanvas::DEPTH_BUFFER )
158                 ogltype |= GL_DEPTH_BUFFER_BIT;
159         glClear(ogltype);
160 }
161
162 int KX_BlenderCanvas::GetWidth(
163 ) const {
164         return m_frame_rect.GetWidth();
165 }
166
167 int KX_BlenderCanvas::GetHeight(
168 ) const {
169         return m_frame_rect.GetHeight();
170 }
171
172 int KX_BlenderCanvas::GetMouseX(int x)
173 {
174         int left = GetWindowArea().GetLeft();
175         return x - (left - m_area_left);
176 }
177
178 int KX_BlenderCanvas::GetMouseY(int y)
179 {
180         int top = GetWindowArea().GetTop();
181         return y - (m_area_top - top);
182 }
183
184 float KX_BlenderCanvas::GetMouseNormalizedX(int x)
185 {
186         int can_x = GetMouseX(x);
187         return float(can_x)/this->GetWidth();
188 }
189
190 float KX_BlenderCanvas::GetMouseNormalizedY(int y)
191 {
192         int can_y = GetMouseY(y);
193         return float(can_y)/this->GetHeight();
194 }
195
196 RAS_Rect &
197 KX_BlenderCanvas::
198 GetWindowArea(
199 ) {
200         return m_area_rect;
201 }
202
203         void
204 KX_BlenderCanvas::
205 SetViewPort(
206         int x1, int y1,
207         int x2, int y2
208 ) {
209         /* x1 and y1 are the min pixel coordinate (e.g. 0)
210          * x2 and y2 are the max pixel coordinate
211          * the width,height is calculated including both pixels
212          * therefore: max - min + 1
213          */
214         int vp_width = (x2 - x1) + 1;
215         int vp_height = (y2 - y1) + 1;
216         int minx = m_frame_rect.GetLeft();
217         int miny = m_frame_rect.GetBottom();
218
219         m_area_rect.SetLeft(minx + x1);
220         m_area_rect.SetBottom(miny + y1);
221         m_area_rect.SetRight(minx + x2);
222         m_area_rect.SetTop(miny + y2);
223
224         m_viewport[0] = minx+x1;
225         m_viewport[1] = miny+y1;
226         m_viewport[2] = vp_width;
227         m_viewport[3] = vp_height;
228
229         glViewport(minx + x1, miny + y1, vp_width, vp_height);
230         glScissor(minx + x1, miny + y1, vp_width, vp_height);
231 }
232
233         void
234 KX_BlenderCanvas::
235 UpdateViewPort(
236         int x1, int y1,
237         int x2, int y2
238 ) {
239         m_viewport[0] = x1;
240         m_viewport[1] = y1;
241         m_viewport[2] = x2;
242         m_viewport[3] = y2;
243 }
244
245         const int*
246 KX_BlenderCanvas::
247 GetViewPort() {
248 #ifdef DEBUG
249         // If we're in a debug build, we might as well make sure our values don't differ
250         // from what the gpu thinks we have. This could lead to nasty, hard to find bugs.
251         int viewport[4];
252         glGetIntegerv(GL_VIEWPORT, viewport);
253         assert(viewport[0] == m_viewport[0]);
254         assert(viewport[1] == m_viewport[1]);
255         assert(viewport[2] == m_viewport[2]);
256         assert(viewport[3] == m_viewport[3]);
257 #endif
258
259         return m_viewport;
260 }
261
262 void KX_BlenderCanvas::SetMouseState(RAS_MouseState mousestate)
263 {
264         m_mousestate = mousestate;
265
266         switch (mousestate)
267         {
268         case MOUSE_INVISIBLE:
269                 {
270                         WM_cursor_set(m_win, CURSOR_NONE);
271                         break;
272                 }
273         case MOUSE_WAIT:
274                 {
275                         WM_cursor_set(m_win, CURSOR_WAIT);
276                         break;
277                 }
278         case MOUSE_NORMAL:
279                 {
280                         WM_cursor_set(m_win, CURSOR_STD);
281                         break;
282                 }
283         default:
284                 {
285                 }
286         }
287 }
288
289
290
291 //      (0,0) is top left, (width,height) is bottom right
292 void KX_BlenderCanvas::SetMousePosition(int x,int y)
293 {
294         int winX = m_frame_rect.GetLeft();
295         int winY = m_frame_rect.GetBottom();
296         int winH = m_frame_rect.GetHeight();
297         
298         WM_cursor_warp(m_win, winX + x, winY + (winH-y));
299 }
300
301
302 /* get shot from frontbuffer sort of a copy from screendump.c */
303 static unsigned int *screenshot(ScrArea *curarea, int *dumpsx, int *dumpsy)
304 {
305         int x=0, y=0;
306         unsigned int *dumprect= NULL;
307
308         x= curarea->totrct.xmin;
309         y= curarea->totrct.ymin;
310         *dumpsx= curarea->totrct.xmax-x;
311         *dumpsy= curarea->totrct.ymax-y;
312
313         if (*dumpsx && *dumpsy) {
314
315                 dumprect= (unsigned int *)MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
316                 glReadBuffer(GL_FRONT);
317                 glReadPixels(x, y, *dumpsx, *dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
318                 glFinish();
319                 glReadBuffer(GL_BACK);
320         }
321
322         return dumprect;
323 }
324
325 void KX_BlenderCanvas::MakeScreenShot(const char *filename)
326 {
327         ScrArea area_dummy= {0};
328         bScreen *screen = m_win->screen;
329         unsigned int *dumprect;
330         int dumpsx, dumpsy;
331
332         area_dummy.totrct.xmin = m_frame_rect.GetLeft();
333         area_dummy.totrct.xmax = m_frame_rect.GetRight();
334         area_dummy.totrct.ymin = m_frame_rect.GetBottom();
335         area_dummy.totrct.ymax = m_frame_rect.GetTop();
336
337         dumprect = screenshot(&area_dummy, &dumpsx, &dumpsy);
338
339         if (dumprect) {
340                 /* initialize image file format data */
341                 Scene *scene = (screen)? screen->scene: NULL;
342                 ImageFormatData im_format;
343
344                 if (scene)
345                         im_format = scene->r.im_format;
346                 else
347                         BKE_imformat_defaults(&im_format);
348
349                 /* create file path */
350                 char path[FILE_MAX];
351                 BLI_strncpy(path, filename, sizeof(path));
352                 BLI_path_abs(path, G.main->name);
353                 BKE_add_image_extension_from_type(path, im_format.imtype);
354
355                 /* create and save imbuf */
356                 ImBuf *ibuf = IMB_allocImBuf(dumpsx, dumpsy, 24, 0);
357                 ibuf->rect = dumprect;
358
359                 BKE_imbuf_write_as(ibuf, path, &im_format, false);
360
361                 ibuf->rect = NULL;
362                 IMB_freeImBuf(ibuf);
363                 MEM_freeN(dumprect);
364         }
365 }