xref: /oneTBB/examples/common/gui/video.hpp (revision b15aabb3)
1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 #ifndef TBB_examples_video_H
18 #define TBB_examples_video_H
19 
20 #include <cassert>
21 #include <cstddef>
22 #if _MSC_VER
23 #include <stddef.h> // for uintptr_t
24 #else
25 #include <stdint.h> // for uintptr_t
26 #endif
27 #if _WIN32 || _WIN64
28 #include <windows.h>
29 #else
30 #include <unistd.h>
31 #endif
32 
33 typedef unsigned int color_t;
34 typedef unsigned char colorcomp_t;
35 typedef signed char depth_t;
36 
37 //! Class for getting access to drawing memory
38 class drawing_memory {
39     uintptr_t my_address;
40 
41 public:
42     depth_t pixel_depth;
43     int sizex, sizey;
44     //! Get drawing memory
get_address() const45     inline char *get_address() const {
46         return reinterpret_cast<char *>(my_address);
47     }
48     //! Get drawing memory size
get_size() const49     inline int get_size() const {
50         return ((pixel_depth > 16) ? 4 : 2) * sizex * sizey;
51     }
52     //! Set drawing memory
set_address(char * mem)53     inline void set_address(char *mem) {
54         my_address = reinterpret_cast<uintptr_t>(mem);
55     }
56 
57     friend class drawing_area;
58     friend class video;
59 };
60 
61 //! Simple proxy class for managing of different video systems
62 class video {
63     //! colorspace information
64     depth_t depth, red_shift, green_shift, blue_shift;
65     color_t red_mask, green_mask, blue_mask;
66     friend class drawing_area;
67 
68 public:
69     //! Constructor
70     video();
71     //! Destructor
72     ~video();
73     //! member to set window name
74     const char *title;
75     //! true is enable to show fps
76     bool calc_fps;
77     //! if true: on windows fork processing thread for on_process(), on non-windows note that next_frame() is called concurrently.
78     bool threaded;
79     //! true while running within main_loop()
80     bool running;
81     //! if true, do gui updating
82     bool updating;
83     //! initialize graphical video system
84     bool init_window(int sizex, int sizey);
85     //! initialize console. returns true if console is available
86     bool init_console();
87     //! terminate video system
88     void terminate();
89     //! Do standard event & processing loop. Use threaded = true to separate event/updating loop from frame processing
90     void main_loop();
91     //! Process next frame
92     bool next_frame();
93     //! Change window title
94     void show_title();
95     //! translate RGB components into packed type
96     inline color_t get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const;
97     //! Get drawing memory descriptor
98     inline drawing_memory get_drawing_memory() const;
99 
100     //! code of the ESCape key
101     static const int esc_key = 27;
102     //! Mouse events handler.
on_mouse(int x,int y,int key)103     virtual void on_mouse(int x, int y, int key) {}
104     //! Mouse events handler.
on_key(int key)105     virtual void on_key(int key) {}
106     //! Main processing loop. Redefine with your own
on_process()107     virtual void on_process() {
108         while (next_frame())
109             ;
110     }
111 
112 #ifdef _WINDOWS
113     //! Windows specific members
114     //! if VIDEO_WINMAIN isn't defined then set this just before init() by arguments of WinMain
115     static HINSTANCE win_hInstance;
116     static int win_iCmdShow;
117     //! optionally call it just before init() to set own. Use ascii strings convention
118     void win_set_class(WNDCLASSEX &);
119     //! load and set accelerator table from resources
120     void win_load_accelerators(int idc);
121 #endif
122 };
123 
124 //! Drawing class
125 class drawing_area {
126     const std::size_t base_index, max_index, index_stride;
127     const depth_t pixel_depth;
128     unsigned int *const ptr32;
129     std::size_t index;
130 
131 public:
132     const int start_x, start_y, size_x, size_y;
133     //! constructors
134     drawing_area(int x, int y, int sizex, int sizey);
135     inline drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem);
136     //! destructor
137     inline ~drawing_area();
138     //! update the image
139     void update();
140     //! set current position. local_x could be bigger then size_x
141     inline void set_pos(int local_x, int local_y);
142     //! put pixel in current position with incremental address calculating to next right pixel
143     inline void put_pixel(color_t color);
144     //! draw pixel at position by packed color
set_pixel(int localx,int localy,color_t color)145     void set_pixel(int localx, int localy, color_t color) {
146         set_pos(localx, localy);
147         put_pixel(color);
148     }
149 };
150 
151 extern int g_sizex;
152 extern int g_sizey;
153 extern unsigned int *g_pImg;
154 
get_drawing_memory() const155 inline drawing_memory video::get_drawing_memory() const {
156     drawing_memory dmem;
157     dmem.pixel_depth = depth;
158     dmem.my_address = reinterpret_cast<uintptr_t>(g_pImg);
159     dmem.sizex = g_sizex;
160     dmem.sizey = g_sizey;
161     return dmem;
162 }
163 
get_color(colorcomp_t red,colorcomp_t green,colorcomp_t blue) const164 inline color_t video::get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const {
165     if (red_shift == 16) // only for depth == 24 && red_shift > blue_shift
166         return (red << 16) | (green << 8) | blue;
167     else if (depth >= 24)
168         return
169 #if __ANDROID__
170             // Setting Alpha to 0xFF
171             0xFF000000 |
172 #endif
173             (red << red_shift) | (green << green_shift) | (blue << blue_shift);
174     else if (depth > 0) {
175         depth_t bs = blue_shift, rs = red_shift;
176         if (blue_shift < 0)
177             blue >>= -bs, bs = 0;
178         else /*red_shift < 0*/
179             red >>= -rs, rs = 0;
180         return ((red << rs) & red_mask) | ((green << green_shift) & green_mask) |
181                ((blue << bs) & blue_mask);
182     }
183     else { // UYVY colorspace
184         unsigned y, u, v;
185         y = red * 77 + green * 150 + blue * 29; // sum(77+150+29=256) * max(=255):  limit->2^16
186         u = (2048 + (blue << 3) - (y >> 5)) >> 4; // (limit->2^12)>>4
187         v = (2048 + (red << 3) - (y >> 5)) >> 4;
188         y = y >> 8;
189         return u | (y << 8) | (v << 16) | (y << 24);
190     }
191 }
192 
drawing_area(int x,int y,int sizex,int sizey,const drawing_memory & dmem)193 inline drawing_area::drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem)
194         : base_index(y * dmem.sizex + x),
195           max_index(dmem.sizex * dmem.sizey),
196           index_stride(dmem.sizex),
197           pixel_depth(dmem.pixel_depth),
198           ptr32(reinterpret_cast<unsigned int *>(dmem.my_address)),
199           start_x(x),
200           start_y(y),
201           size_x(sizex),
202           size_y(sizey) {
203     assert(x < dmem.sizex);
204     assert(y < dmem.sizey);
205     assert(x + sizex <= dmem.sizex);
206     assert(y + sizey <= dmem.sizey);
207 
208     index = base_index; // current index
209 }
210 
set_pos(int local_x,int local_y)211 inline void drawing_area::set_pos(int local_x, int local_y) {
212     index = base_index + local_x + local_y * index_stride;
213 }
214 
put_pixel(color_t color)215 inline void drawing_area::put_pixel(color_t color) {
216     assert(index < max_index);
217     if (pixel_depth > 16)
218         ptr32[index++] = color;
219     else if (pixel_depth > 0)
220         ((unsigned short *)ptr32)[index++] = (unsigned short)color;
221     else { // UYVY colorspace
222         if (index & 1)
223             color >>= 16;
224         ((unsigned short *)ptr32)[index++] = (unsigned short)color;
225     }
226 }
227 
~drawing_area()228 inline drawing_area::~drawing_area() {}
229 
230 #if defined(_WINDOWS) && (defined(VIDEO_WINMAIN) || defined(VIDEO_WINMAIN_ARGS))
231 #include <cstdlib>
232 //! define WinMain for subsystem:windows.
233 #ifdef VIDEO_WINMAIN_ARGS
234 int main(int, char *[]);
235 #else
236 int main();
237 #endif
WinMain(HINSTANCE hInstance,HINSTANCE,PSTR szCmdLine,int iCmdShow)238 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow) {
239     video::win_hInstance = hInstance;
240     video::win_iCmdShow = iCmdShow;
241 #ifdef VIDEO_WINMAIN_ARGS
242     return main(__argc, __argv);
243 #else
244     return main();
245 #endif
246 }
247 #endif
248 
249 #endif /* TBB_examples_video_H */
250