PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
SDLUtility.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/platforms/sdl/SDLUtility.h
4// Purpose: Contains miscellaneous utility functions.
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
28#include "SDLUtility.h"
29#include "../../objects/PColor.h"
30#include "../../utility/PError.h"
31#include "../../base/PList.h"
32#include "../../base/PComplexData.h"
33#include "PlatformWindow.h"
34#include "SDL.h"
35#include "SDL_image.h"
36
37//#if !defined(PEBL_OSX)
38//#include <png.h>
39//#endif
40#include <math.h>
41#include <iostream>
42
43
44// cout removed - use cerr for debug output
45using std::flush;
46using std::endl;
47
49
50
52{
53 SDL_Color scolor;
54 scolor.r = pcolor.GetRed();
55 scolor.g = pcolor.GetGreen();
56 scolor.b = pcolor.GetBlue();
57 scolor.a = pcolor.GetAlpha();
58
59 return scolor;
60}
61
63{
64
65 return PColor(scolor.r, scolor.g, scolor.b, scolor.a);
66}
67
68
69
70
72void SDLUtility::DrawPixel(SDL_Renderer *renderer, PlatformWidget * widget, int x, int y, PColor pcolor)
73{
74
75 cerr << "drawing " << x << ","<< y << endl;
76#if 0
77 if(renderer)
78 cerr << "Line renderer: " << renderer << endl;
79 else
80 cerr << "renderer is null\n";
81
82#endif
83
84 cerr <<" texture " << widget->GetSDL_Texture() << endl;
85
86 SDL_SetRenderTarget(renderer, widget->GetSDL_Texture());
87 // SDL_Color sdlcolor = PColorToSDLColor(pcolor);
88 cerr << pcolor.GetRed() <<
89 "," << pcolor.GetGreen() << "," <<
90 pcolor.GetBlue() << "," << pcolor.GetAlpha() << endl;
91
92
93
94 SDL_SetRenderDrawColor(renderer, pcolor.GetRed(), pcolor.GetGreen(), pcolor.GetBlue(), pcolor.GetAlpha());
95 //this offset may be needed because renderer references coordinates to the window,
96 //not the widget. It may screw up drawing on center-coordinated widgets
97 SDL_RenderPresent(renderer);
98
99 //like images and labels.
100 SDL_RenderDrawPoint(renderer,(int)(widget->GetX()+x),(int)(widget->GetY()+y));
101
102 // SDL_SetRenderTarget(renderer,NULL);
103}
104
106void SDLUtility::DrawLine(SDL_Renderer *renderer,
107 PlatformWidget* widget,
108 int x1, int y1, int x2, int y2, PColor pcolor)
109{
110 // SDL_Color sdlcolor = PColorToSDLColor(pcolor);
111 //to draw to a widget, we need to set render target:
112 int out = SDL_SetRenderTarget(renderer, widget->GetSDL_Texture());
113
114 if(out<0)
115 {
116 cerr << "setrendertarget result in drawline: "<< out <<endl;
117 cerr << SDL_GetError() <<endl;
118 }
119
120 SDL_SetRenderDrawColor(renderer,
121 pcolor.GetRed(), pcolor.GetGreen(),
122 pcolor.GetBlue(), pcolor.GetAlpha());
123
124
125 //x and y position are absolute to window, so we need to adjust to
126 //widget location
127
128 int newX1 = x1;
129 int newY1 = y1;
130 int newX2 = x2;
131 int newY2 = y2;
132
133
134 SDL_RenderDrawLine(renderer,newX1,newY1,newX2,newY2);
135 SDL_SetRenderTarget(renderer,NULL);
136
137}
138
139
140
141/*
142 * Return the pixel value at (x, y)
143 * NOTE: The surface must be locked before calling this!
144 */
145Uint32 SDLUtility::GetPixel(SDL_Surface *surface, int x, int y)
146 {
147 int bpp = surface->format->BytesPerPixel;
148 /* Here p is the address to the pixel we want to retrieve */
149 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
150
151 switch (bpp) {
152 case 1:
153 return *p;
154
155 case 2:
156 return *(Uint16 *)p;
157
158 case 3:
159 if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
160 return p[0] << 16 | p[1] << 8 | p[2];
161 else
162 return p[0] | p[1] << 8 | p[2] << 16;
163
164 case 4:
165 return *(Uint32 *)p;
166
167 default:
168 return 0; /* shouldn't happen, but avoids warnings */
169 } // switch
170 }
171
172
174PColor SDLUtility::GetPixelColor(SDL_Surface *surface, int x, int y)
175{
176 Uint32 pxl =GetPixel(surface,x,y);
177 Uint8 r;
178 Uint8 g;
179 Uint8 b;
180
181 SDL_GetRGB(pxl, surface->format, &r,&g,&b);
182
183 // cerr <<"Uint pxl:" << pxl << endl;
184 PColor col = PColor(r,g,b,0);
185 return col;
186}
187
188
189
190/*
191 * Return the pixel value at (x, y)
192
193 */
194
195 //internet indicates that the texture needs to be in streaming mode,
196//and then it needs to be locked.
197Uint32 SDLUtility::GetPixel(SDL_Renderer *renderer, SDL_Texture * texture, int x, int y)
198 {
199
200 int pitch,w,h;
201 void* pixels;
202 Uint32 format;
203 SDL_SetTextureBlendMode(texture,SDL_BLENDMODE_BLEND);
204 SDL_QueryTexture(texture,&format,&w,&h,&pitch);
205 SDL_LockTexture(texture,NULL,&pixels,&pitch);
206 Uint32 * upixels = (Uint32*) pixels;
207
208 // int pixel[3];
209 // SDL_Rect rect = {x,y,1,1};
210 // SDL_RenderReadPixels(renderer,&rect,1,(void *)pixel,1*4);
211
212 int i = pitch*(w*x+y);
213
214 //upixels[i] should be the right pixel
215 Uint32 pixel = upixels[i];
216 SDL_UnlockTexture(texture);
217 return pixel;
218
219
220#ifdef SDL2_DELETE
221 int bpp = surface->format->BytesPerPixel;
222 /* Here p is the address to the pixel we want to retrieve */
223 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
224
225 switch (bpp) {
226 case 1:
227 return *p;
228
229 case 2:
230 return *(Uint16 *)p;
231
232 case 3:
233 if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
234 return p[0] << 16 | p[1] << 8 | p[2];
235 else
236 return p[0] | p[1] << 8 | p[2] << 16;
237
238 case 4:
239 return *(Uint32 *)p;
240
241 default:
242
243 return 0; /* shouldn't happen, but avoids warnings */
244 } // switch
245#endif
246
247
248 }
249
250
251
252
254PColor SDLUtility::GetPixelColor(SDL_Renderer *renderer, SDL_Texture * texture, int x, int y)
255{
256
257
258
259 int pitch,w,h;
260 void* pixels;
261 Uint32 format;
262
263
264 SDL_SetTextureBlendMode(texture,SDL_BLENDMODE_BLEND);
265 SDL_QueryTexture(texture,&format,&w,&h,&pitch);
266 int success = SDL_LockTexture(texture,NULL,&pixels,&pitch);
267 if(success<0)
268 {
269 cerr << SDL_GetError() << endl;
270 }
271 Uint32 * upixels = (Uint32*) pixels;
272 SDL_PixelFormat* fmt= SDL_AllocFormat(format);
273 // int pixel[3];
274 // SDL_Rect rect = {x,y,1,1};
275 // SDL_RenderReadPixels(renderer,&rect,1,(void *)pixel,1*4);
276
277 int i = pitch*(w*y+x);
278
279 //upixels[i] should be the right pixel
280 Uint32 pixel = upixels[i];
281 SDL_UnlockTexture(texture);
282
283
284
285
286 Uint8 r=0;
287 Uint8 g=0;
288 Uint8 b=0;
289 Uint8 a = 0;
290
291 SDL_GetRGBA(pixel,fmt, &r,&g,&b,&a);
292
293 // cerr <<"Uint pxl:" << pxl << endl;
294 //#endif
295
296 PColor col = PColor(r,g,b,a);
297 return col;
298}
299
300
301
302int SDLUtility::WritePNG(SDL_Renderer * renderer, SDL_Rect * rect, const std::string fname)
303{
304
305
306
307 //SDL_GetRendererOutputSize(renderer,rect->w,rect->h);
308 SDL_Surface *sshot = SDL_CreateRGBSurface(0, rect->w,rect->h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
309 SDL_RenderReadPixels(renderer, rect, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch);
310 //SDL_SaveBMP(sshot, fname.c_str());
311 //This is a secrit undocumented function in sdl_image
312 int result =IMG_SavePNG(sshot, fname.c_str());
313 SDL_FreeSurface(sshot);
314
315 //returns 0 on success!
316 return result;
317
318}
319
321{
322
323
324
325 int i;
326
327 // Declare display mode structure to be filled in.
328 SDL_DisplayMode current;
329
330 // Get current display mode of all displays.
331 for(i = 0; i < SDL_GetNumVideoDisplays(); ++i){
332
333 int should_be_zero = SDL_GetCurrentDisplayMode(i, &current);
334
335 if(should_be_zero != 0)
336 // In case of error...
337 SDL_Log("Could not get display mode for video display #%d: %s", i, SDL_GetError());
338
339 else
340 // On success, print the current display mode.
341 SDL_Log("Display #%d: current display mode is %dx%dpx @ %dhz. \n", i, current.w, current.h, current.refresh_rate);
342
343 }
344
345
346 //THere is a new function for this, which depends
347 // on the actual screen
348
349 SDL_DisplayMode info;// = SDL_GetVideoInfo();
350 int success = SDL_GetCurrentDisplayMode(0,&info);
351 //might also use SDL_GetDesktopDisplayMode()
352 cerr << "SUCCESS at getting display mode?:" <<success << endl;
353
354 int w,h,rate;
355 if(success==0)
356 {
357 cerr << info.w << "," << info.h <<"," << info.refresh_rate << endl;
358 w = info.w;
359 h = info.h;
360 rate =info.refresh_rate;
361
362 } else {
363 cerr << "SDL_Init failed: " << SDL_GetError() << endl;
364 PError::SignalFatalError(SDL_GetError());
365 }
366
367
368 PList * newlist = new PList();
369 newlist->PushBack(Variant(w));
370 newlist->PushBack(Variant(h));
371
373 PComplexData * pcd=new PComplexData(newlist2);
374 return Variant(pcd);
375
376}
377
378
379void SDLUtility::CopyToClipboard(std::string text)
380{
381
382 int out = SDL_SetClipboardText(text.c_str());
383 if(out<0)
384 {
385 PError::SignalWarning("Failed to copy text to clipboard\n");
386 }
387}
388
390{
391 Variant out="";
392 if(SDL_HasClipboardText())
393 {
394 char * text = SDL_GetClipboardText();
395 out = Variant(text);
396 SDL_free(text);
397 }
398
399 return out;
400}
401
402
404 const char* message)
405{
406
407 SDL_Window * window = pwindow->GetSDLWindow();
408 return SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
409 "An error occurred\n",
410 message,window);
411}
412
413
415{
416 // std::cerr << SDL_GetPerformanceFrequency() <<std::endl;
417 std::cerr << SDL_GetPerformanceCounter() <<"/"<< SDL_GetPerformanceFrequency() <<std::endl;
418 return ((long double)SDL_GetPerformanceCounter())/(long double)SDL_GetPerformanceFrequency()*1000.0;
419}
420
421
423{
424
425 PList * plist = new PList();
426 PComplexData*pcd=NULL;
427
428 if(printout)
429 {
430 std::cerr << "=================================================\n";
431 std::cerr << " Available drivers\n";
432 std::cerr << "=================================================\n";
433 }
434
435 int numdrivers = SDL_GetNumRenderDrivers ();
436 if(printout) std::cerr << "Render driver count: " << numdrivers << endl;
437 for (int i=0; i<numdrivers; i++)
438 {
439 SDL_RendererInfo drinfo;
440 SDL_GetRenderDriverInfo (i, &drinfo);
441 if(printout)
442 {
443 cerr << "Driver name ("<<i<<"): " << drinfo.name << endl;
444 if (drinfo.flags & SDL_RENDERER_SOFTWARE) std::cerr << " the renderer is a software fallback" << endl;
445 if (drinfo.flags & SDL_RENDERER_ACCELERATED) std::cerr << " the renderer uses hardware acceleration" << endl;
446 if (drinfo.flags & SDL_RENDERER_PRESENTVSYNC) std::cerr << " present is synchronized with the refresh rate" << endl;
447 if (drinfo.flags & SDL_RENDERER_TARGETTEXTURE) std::cerr << " the renderer supports rendering to texture" << endl;
448 }
449 plist->PushBack(Variant(drinfo.name));
450 }
451
452 if(printout) std::cerr << "=================================================\n";
453
455 pcd = new PComplexData(tmplist);
456 Variant tmp = Variant(pcd);
457 delete pcd;
458
459 return tmp;
460}
#define NULL
Definition BinReloc.cpp:317
int GetRed() const
Definition PColor.cpp:226
int GetAlpha() const
Definition PColor.cpp:229
int GetBlue() const
Definition PColor.cpp:228
int GetGreen() const
Definition PColor.cpp:227
Definition PList.h:45
void PushBack(const Variant &v)
Definition PList.cpp:149
virtual pInt GetX() const
Definition PWidget.h:82
virtual pInt GetY() const
Definition PWidget.h:83
virtual SDL_Texture * GetSDL_Texture()
Used to extract an SDL surface from the widget. Used by children drawing themselves on their parent.
SDL_Window * GetSDLWindow()
void SignalWarning(const std::string &message)
Definition PError.cpp:119
void SignalFatalError(const std::string &message)
Variant GetDriverList(bool printout=true)
PColor SDLColorToPColor(SDL_Color scolor)
This converts between an SDL Color and a PColor
Variant CopyFromClipboard()
int WritePNG(SDL_Renderer *renderer, SDL_Rect *rect, const std::string fname)
void CopyToClipboard(std::string text)
int PopupErrorBox(PlatformWindow *pwindow, const char *message)
SDL_Color PColorToSDLColor(PColor pcolor)
This converts between a PColor and an SDL color.
void DrawLine(SDL_Renderer *renderer, PlatformWidget *pwidget, int x1, int y1, int x2, int y2, PColor color)
This sets a pixel to be a certain color.
Variant GetCurrentScreenResolution()
void DrawPixel(SDL_Renderer *renderer, PlatformWidget *pwidget, int x, int y, PColor color)
This sets a pixel to be a certain color.
long double GetTimeHP()
PColor GetPixelColor(SDL_Surface *surface, int x, int y)
This extracts the color of a pixel.
Uint32 GetPixel(SDL_Surface *surface, int x, int y)