You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
8.1 KiB
244 lines
8.1 KiB
/*
|
|
Copyright 2005-2014 Intel Corporation. All Rights Reserved.
|
|
|
|
This file is part of Threading Building Blocks.
|
|
|
|
Threading Building Blocks is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License
|
|
version 2 as published by the Free Software Foundation.
|
|
|
|
Threading Building Blocks is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Threading Building Blocks; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
As a special exception, you may use this file as part of a free software
|
|
library without restriction. Specifically, if other files instantiate
|
|
templates or use macros or inline functions from this file, or you compile
|
|
this file and link it with other files to produce an executable, this
|
|
file does not by itself cause the resulting executable to be covered by
|
|
the GNU General Public License. This exception does not however
|
|
invalidate any other reasons why the executable file might be covered by
|
|
the GNU General Public License.
|
|
*/
|
|
|
|
#ifndef __VIDEO_H__
|
|
#define __VIDEO_H__
|
|
|
|
#include <cassert>
|
|
#if _MSC_VER
|
|
#include <stddef.h> // for uintptr_t
|
|
#else
|
|
#include <stdint.h> // for uintptr_t
|
|
#endif
|
|
#if _WIN32 || _WIN64
|
|
#include <windows.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
typedef unsigned int color_t;
|
|
typedef unsigned char colorcomp_t;
|
|
typedef signed char depth_t;
|
|
|
|
//! Class for getting access to drawing memory
|
|
class drawing_memory
|
|
{
|
|
#ifdef __TBB_MIC_OFFLOAD
|
|
// The address is kept as uintptr_t since
|
|
// the compiler could not offload a pointer
|
|
#endif
|
|
uintptr_t my_address;
|
|
public:
|
|
depth_t pixel_depth;
|
|
int sizex, sizey;
|
|
//! Get drawing memory
|
|
inline char* get_address() const { return reinterpret_cast<char*>(my_address); }
|
|
//! Get drawing memory size
|
|
inline int get_size() const { return ((pixel_depth>16) ? 4:2) * sizex * sizey; }
|
|
//! Set drawing memory
|
|
inline void set_address(char *mem) { my_address = reinterpret_cast<uintptr_t>(mem); }
|
|
|
|
friend class drawing_area;
|
|
friend class video;
|
|
};
|
|
|
|
//! Simple proxy class for managing of different video systems
|
|
class video
|
|
{
|
|
//! colorspace information
|
|
depth_t depth, red_shift, green_shift, blue_shift;
|
|
color_t red_mask, green_mask, blue_mask;
|
|
friend class drawing_area;
|
|
|
|
public:
|
|
//! Constructor
|
|
video();
|
|
//! Destructor
|
|
~video();
|
|
//! member to set window name
|
|
const char *title;
|
|
//! true is enable to show fps
|
|
bool calc_fps;
|
|
//! if true: on windows fork processing thread for on_process(), on non-windows note that next_frame() is called concurrently.
|
|
bool threaded;
|
|
//! true while running within main_loop()
|
|
bool running;
|
|
//! if true, do gui updating
|
|
bool updating;
|
|
//! initialize graphical video system
|
|
bool init_window(int sizex, int sizey);
|
|
//! initialize console. returns true if console is available
|
|
bool init_console();
|
|
//! terminate video system
|
|
void terminate();
|
|
//! Do standard event & processing loop. Use threaded = true to separate event/updating loop from frame processing
|
|
void main_loop();
|
|
//! Process next frame
|
|
bool next_frame();
|
|
//! Change window title
|
|
void show_title();
|
|
//! translate RGB components into packed type
|
|
inline color_t get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const;
|
|
//! Get drawing memory descriptor
|
|
inline drawing_memory get_drawing_memory() const;
|
|
|
|
//! code of the ESCape key
|
|
static const int esc_key = 27;
|
|
//! Mouse events handler.
|
|
virtual void on_mouse(int x, int y, int key) { }
|
|
//! Mouse events handler.
|
|
virtual void on_key(int key) { }
|
|
//! Main processing loop. Redefine with your own
|
|
virtual void on_process() { while(next_frame()); }
|
|
|
|
#ifdef _WINDOWS
|
|
//! Windows specific members
|
|
//! if VIDEO_WINMAIN isn't defined then set this just before init() by arguments of WinMain
|
|
static HINSTANCE win_hInstance; static int win_iCmdShow;
|
|
//! optionally call it just before init() to set own. Use ascii strings convention
|
|
void win_set_class(WNDCLASSEX &);
|
|
//! load and set accelerator table from resources
|
|
void win_load_accelerators(int idc);
|
|
#endif
|
|
};
|
|
|
|
//! Drawing class
|
|
class drawing_area
|
|
{
|
|
const size_t base_index, max_index, index_stride;
|
|
const depth_t pixel_depth;
|
|
unsigned int * const ptr32;
|
|
size_t index;
|
|
public:
|
|
const int start_x, start_y, size_x, size_y;
|
|
//! constructors
|
|
drawing_area(int x, int y, int sizex, int sizey);
|
|
inline drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem);
|
|
//! destructor
|
|
inline ~drawing_area();
|
|
//! update the image
|
|
void update();
|
|
//! set current position. local_x could be bigger then size_x
|
|
inline void set_pos(int local_x, int local_y);
|
|
//! put pixel in current position with incremental address calculating to next right pixel
|
|
inline void put_pixel(color_t color);
|
|
//! draw pixel at position by packed color
|
|
void set_pixel(int localx, int localy, color_t color)
|
|
{ set_pos(localx, localy); put_pixel(color); }
|
|
};
|
|
|
|
extern int g_sizex;
|
|
extern int g_sizey;
|
|
extern unsigned int *g_pImg;
|
|
|
|
inline drawing_memory video::get_drawing_memory() const
|
|
{
|
|
drawing_memory dmem;
|
|
dmem.pixel_depth = depth;
|
|
dmem.my_address = reinterpret_cast<uintptr_t>(g_pImg);
|
|
dmem.sizex = g_sizex;
|
|
dmem.sizey = g_sizey;
|
|
return dmem;
|
|
}
|
|
|
|
inline color_t video::get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const
|
|
{
|
|
if(red_shift == 16) // only for depth == 24 && red_shift > blue_shift
|
|
return (red<<16) | (green<<8) | blue;
|
|
else if(depth >= 24)
|
|
return (red<<red_shift) | (green<<green_shift) | (blue<<blue_shift);
|
|
else if(depth > 0) {
|
|
register depth_t bs = blue_shift, rs = red_shift;
|
|
if(blue_shift < 0) blue >>= -bs, bs = 0;
|
|
else /*red_shift < 0*/ red >>= -rs, rs = 0;
|
|
return ((red<<rs)&red_mask) | ((green<<green_shift)&green_mask) | ((blue<<bs)&blue_mask);
|
|
} else { // UYVY colorspace
|
|
register unsigned y, u, v;
|
|
y = red * 77 + green * 150 + blue * 29; // sum(77+150+29=256) * max(=255): limit->2^16
|
|
u = (2048 + (blue << 3) - (y >> 5)) >> 4; // (limit->2^12)>>4
|
|
v = (2048 + (red << 3) - (y >> 5)) >> 4;
|
|
y = y >> 8;
|
|
return u | (y << 8) | (v << 16) | (y << 24);
|
|
}
|
|
}
|
|
|
|
inline drawing_area::drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem)
|
|
: start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(dmem.pixel_depth),
|
|
base_index(y*dmem.sizex + x), max_index(dmem.sizex*dmem.sizey), index_stride(dmem.sizex),
|
|
ptr32(reinterpret_cast<unsigned int*>(dmem.my_address))
|
|
{
|
|
assert(x < dmem.sizex); assert(y < dmem.sizey);
|
|
assert(x+sizex <= dmem.sizex); assert(y+sizey <= dmem.sizey);
|
|
|
|
index = base_index; // current index
|
|
}
|
|
|
|
inline void drawing_area::set_pos(int local_x, int local_y)
|
|
{
|
|
index = base_index + local_x + local_y*index_stride;
|
|
}
|
|
|
|
inline void drawing_area::put_pixel(color_t color)
|
|
{
|
|
assert(index < max_index);
|
|
if(pixel_depth > 16) ptr32[index++] = color;
|
|
else if(pixel_depth > 0)
|
|
((unsigned short*)ptr32)[index++] = (unsigned short)color;
|
|
else { // UYVY colorspace
|
|
if(index&1) color >>= 16;
|
|
((unsigned short*)ptr32)[index++] = (unsigned short)color;
|
|
}
|
|
}
|
|
|
|
inline drawing_area::~drawing_area()
|
|
{
|
|
#if ! __TBB_DEFINE_MIC
|
|
update();
|
|
#endif
|
|
}
|
|
|
|
#if defined(_WINDOWS) && (defined(VIDEO_WINMAIN) || defined(VIDEO_WINMAIN_ARGS) )
|
|
#include <cstdlib>
|
|
//! define WinMain for subsystem:windows.
|
|
#ifdef VIDEO_WINMAIN_ARGS
|
|
int main(int, char *[]);
|
|
#else
|
|
int main();
|
|
#endif
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow)
|
|
{
|
|
video::win_hInstance = hInstance; video::win_iCmdShow = iCmdShow;
|
|
#ifdef VIDEO_WINMAIN_ARGS
|
|
return main(__argc, __argv);
|
|
#else
|
|
return main();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#endif// __VIDEO_H__
|