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 45 inline char *get_address() const { 46 return reinterpret_cast<char *>(my_address); 47 } 48 //! Get drawing memory size 49 inline int get_size() const { 50 return ((pixel_depth > 16) ? 4 : 2) * sizex * sizey; 51 } 52 //! Set drawing memory 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. 103 virtual void on_mouse(int x, int y, int key) {} 104 //! Mouse events handler. 105 virtual void on_key(int key) {} 106 //! Main processing loop. Redefine with your own 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 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 155 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 164 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 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 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 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 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 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