qtsdl2::qtsdl2(QWidget *parent, Qt::WFlags flags) : QWidget(parent, flags) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { puts("# error initializing SDL"); puts(SDL_GetError()); return ; } ui.setupUi(this); resize(600, 400); m_Cap = new CvCapture_FFMPEG; //m_Cap->open("rtsp://159.99.251.194/"); m_Cap->open("r.mp4"); m_SdlWin = SDL_CreateWindowFrom((void *)this->winId()); /* 0 stand for direct3d */ m_SdlRender = SDL_CreateRenderer(m_SdlWin, 0, 0); int w = width(); int h = height(); m_pTex = SDL_CreateTexture(m_SdlRender, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, width(), height()); m_UpdateSize = false; m_SdlThread = new tthread::thread(qtsdl2::Run, (void *)this); }
WindowContext::WindowContext(const unsigned int windowID, void *windowHandle) : m_windowID(windowID) , m_readerThreads(4) , m_decoderThreads(4) { m_sdlWindow = SDL_CreateWindowFrom(windowHandle); m_sdlRenderer = SDL_CreateRenderer(m_sdlWindow, -1, SDL_RENDERER_ACCELERATED); }
bool ffplayer::CreateRender() { std::lock_guard<std::recursive_mutex> lock(g_mutexSDL); m_sdlWindow = SDL_CreateWindowFrom((void*)m_hwnd); // SDL_ShowWindow(sdlWindow); //获取当前可用画图驱动 window中有3个,第一个为d3d,第二个为opengl,第三个为software //创建渲染器,第二个参数为选用的画图驱动,0代表d3d if (m_sdlWindow) m_pRender = SDL_CreateRenderer(m_sdlWindow, 0, SDL_RENDERER_ACCELERATED); return true; }
static int lua_SDL_CreateWindowFrom(State & state){ Stack * stack = state.stack; Window * interfaceWindow = state.getInterface<Window>("LuaSDL_Window"); if (stack->is<LUA_TLIGHTUSERDATA>(1)){ void * data = stack->to<void*>(1); if (data){ SDL_Window * window = SDL_CreateWindowFrom(data); if (window){ interfaceWindow->push(window); return 1; } } } return 0; }
int main(int argc, char *argv[]) { int i, done; const char *driver; SDL_Window *window; SDL_Texture *sprite; int window_w, window_h; int sprite_w, sprite_h; SDL_Event event; if (SDL_VideoInit(NULL, 0) < 0) { fprintf(stderr, "Couldn't initialize SDL video: %s\n", SDL_GetError()); exit(1); } driver = SDL_GetCurrentVideoDriver(); /* Find a native window driver and create a native window */ for (i = 0; factories[i]; ++i) { if (SDL_strcmp(driver, factories[i]->tag) == 0) { factory = factories[i]; break; } } if (!factory) { fprintf(stderr, "Couldn't find native window code for %s driver\n", driver); quit(2); } printf("Creating native window for %s driver\n", driver); native_window = factory->CreateNativeWindow(WINDOW_W, WINDOW_H); if (!native_window) { fprintf(stderr, "Couldn't create native window\n"); quit(3); } window = SDL_CreateWindowFrom(native_window); if (!window) { fprintf(stderr, "Couldn't create SDL window: %s\n", SDL_GetError()); quit(4); } SDL_SetWindowTitle(window, "SDL Native Window Test"); /* Create the renderer */ if (SDL_CreateRenderer(window, -1, 0) < 0) { fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError()); quit(5); } /* Clear the window, load the sprite and go! */ SDL_SelectRenderer(window); SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF); SDL_RenderClear(); sprite = LoadSprite(window, "icon.bmp"); if (!sprite) { quit(6); } /* Allocate memory for the sprite info */ SDL_GetWindowSize(window, &window_w, &window_h); SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h); positions = (SDL_Rect *) SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect)); velocities = (SDL_Rect *) SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect)); if (!positions || !velocities) { fprintf(stderr, "Out of memory!\n"); quit(2); } srand(time(NULL)); for (i = 0; i < NUM_SPRITES; ++i) { positions[i].x = rand() % (window_w - sprite_w); positions[i].y = rand() % (window_h - sprite_h); positions[i].w = sprite_w; positions[i].h = sprite_h; velocities[i].x = 0; velocities[i].y = 0; while (!velocities[i].x && !velocities[i].y) { velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED; velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED; } } /* Main render loop */ done = 0; while (!done) { /* Check for events */ while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_EXPOSED: SDL_SelectRenderer(event.window.windowID); SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF); SDL_RenderClear(); break; } break; case SDL_QUIT: done = 1; break; default: break; } } MoveSprites(window, sprite); } quit(0); }
int CVideoDecoder::open(void) { int ret = 0; bOpen = true; pFormatCtx = avformat_alloc_context(); const int BUF_LEN = (1024 * 200); iobuffer = (unsigned char *)av_malloc(BUF_LEN); avio = avio_alloc_context(iobuffer, BUF_LEN, 0, this, fill_iobuffer, NULL, NULL); pFormatCtx->pb = avio; if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0){ bOpen = false; return -1; // Couldn't open file } // Retrieve stream information if (avformat_find_stream_info(pFormatCtx, NULL)<0){ bOpen = false; return -1; // Couldn't find stream information } // Find the first video stream videoStream = -1; unsigned int i; for (i = 0; i<pFormatCtx->nb_streams; i++) if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; break; } if (videoStream == -1){ bOpen = false; return -1; // Didn't find a video stream } /*AV_SAMPLE_FMT_S16;*/ // Get a pointer to the codec context for the video stream pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec; if (!pCodecCtxOrig){ fprintf(stderr, "Unsupported codec!\n"); bOpen = false; return -1; // Codec not found } // Find the decoder for the video stream pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id); if (pCodec == NULL) { fprintf(stderr, "Unsupported codec!\n"); bOpen = false; return -1; // Codec not found } // Copy context pCodecCtx = avcodec_alloc_context3(pCodec); if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) { fprintf(stderr, "Couldn't copy codec context"); bOpen = false; return -1; // Error copying codec context } // Open codec if (avcodec_open2(pCodecCtx, pCodec, NULL)<0){ bOpen = false; return -1; // Could not open codec } // Allocate video frame pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); // Make a screen to put our video if (hWin){ screen = SDL_CreateWindowFrom(hWin); RECT rc; GetClientRect(hWin, &rc); SDL_SetWindowSize(screen, rc.right - rc.left, rc.bottom - rc.top); rect_dst.x = rect_dst.y = 0; rect_dst.w = rc.right - rc.left; rect_dst.h = rc.bottom - rc.top; } else screen = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, pCodecCtx->width, pCodecCtx->height, 0); renderer = SDL_CreateRenderer(screen, -1, 0); if (!screen) { fprintf(stderr, "SDL: could not set video mode - exiting\n"); bOpen = false; return -1;; } // Allocate a place to put our YUV image on that screen texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV /*SDL_PIXELFORMAT_YV12*/, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height); // initialize SWS context for software scaling sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL ); int numBytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); uint8_t* buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); bOpen = true; //bStop = false; //start(); return ret; }
void CLS_DlgStreamPusher::InitDlgItem() { //进行界面信息的初始化操作 //默认是网络流推送 m_chkSrcType.SetCheck(1); m_blUrl = TRUE; m_edtLocalFilePath.EnableWindow(FALSE); m_btnOpenLocalFile.EnableWindow(FALSE); if (NULL == m_bkBrush) { m_bkBrush = CreateSolidBrush(COLOR_BLACK); } //初始化网络库 av_register_all(); avformat_network_init(); avdevice_register_all(); //初始化directshow库 if (FAILED(CoInitialize(NULL))){ TRACE("CoInitialize Failed!\r\n"); return; } //获取当前连接的视频设备 int iRet= GetDeviceInfo(n_Video); if (iRet < 0){ TRACE("获取视频设备失败!"); return; } //获取当前连接输入的音频设备 iRet = GetDeviceInfo(n_Audio); if (iRet < 0){ TRACE("获取音频设备失败!"); return; } //将获取到的设备信息插入下拉框中 std::map<int, std::vector<std::string>>::iterator iter = m_mapDeviceInfo.begin(); for (; iter != m_mapDeviceInfo.end(); iter ++){ if (n_Video == iter->first){ //视频设备 for (int i = 0; i < iter->second.size(); i ++){ int iCount = m_cboDeviceVideo.GetCount(); m_cboDeviceVideo.InsertString(iCount, iter->second[i].c_str()); } m_cboDeviceVideo.SetCurSel(0); } else if (n_Audio == iter->first){ //音频设备 for (int i = 0; i < iter->second.size(); i ++){ int iCount = m_cboDeviceAudio.GetCount(); m_cboDeviceAudio.InsertString(iCount, iter->second[i].c_str()); } m_cboDeviceAudio.SetCurSel(0); } } //SDL初始化 int flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; int sdlinit = SDL_Init(flags); if (sdlinit) { char * sss = (char*)SDL_GetError(); fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); fprintf(stderr, "(Did you set the DISPLAY variable?)\n"); return; } //将CSTATIC控件和sdl显示窗口关联 HWND hWnd = this->GetDlgItem(IDC_STC_PREVIEW)->GetSafeHwnd(); if (hWnd != NULL) { if (m_pStreamInfo != NULL){ m_pStreamInfo->m_show_screen = SDL_CreateWindowFrom((void*)hWnd); if (m_pStreamInfo->m_show_screen == NULL){ TRACE("SDL_CreateWindowFrom ERR(%d)\n", SDL_GetError()); return; } RECT rectDisPlay; this->GetDlgItem(IDC_STC_PREVIEW)->GetWindowRect(&rectDisPlay); m_pStreamInfo->m_xleft = rectDisPlay.left; m_pStreamInfo->m_ytop = rectDisPlay.top; m_pStreamInfo->m_width = rectDisPlay.right - rectDisPlay.left; m_pStreamInfo->m_height = rectDisPlay.bottom - rectDisPlay.top; //处理显示区域 FillDisplayRect(); m_pStreamInfo->m_sdlRenderer = SDL_CreateRenderer(m_pStreamInfo->m_show_screen, -1, 0); if (m_pStreamInfo->m_sdlRenderer == NULL){ TRACE("SDL_CreateRenderer--sdlRenderer == NULL err(%d)\n", SDL_GetError()); return; } } } //设置SDL事件状态 SDL_EventState(SDL_WINDOWEVENT, SDL_IGNORE); SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_USEREVENT, SDL_IGNORE); if (m_pThreadEvent == NULL){ m_pThreadEvent = AfxBeginThread(Thread_Event, this);//开启线程 } m_edtPusherAddr.SetWindowText("rtmp://5380.lsspublish.aodianyun.com/Young/stream"); return; }
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int width; static int height; static int open = 0; static TCHAR fullPath[MAX_PATH]; static TCHAR fileName[MAX_PATH]; static char u8FullPath[MAX_PATH]; static RECT windowRect; static RECT deskRect; static HWND deskHwnd; static int fullScreen = 0; static long windowStyle; static SDL_Window *sdlWindow = 0; static SDL_Renderer *sdlRenderer = 0; static SDL_Surface *sdlSurface = 0; static SDL_Texture *sdlTexture = 0; static SDL_Rect sdlShowRect; //窗口中显示图像的具体区域 switch (message) { case WM_CREATE: sdlWindow = SDL_CreateWindowFrom(hwnd); sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); sdlSurface = SDL_LoadBMP("PictureViewer.bmp"); sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface); SDL_FreeSurface(sdlSurface); break; case WM_SIZE: if (open == 0) { SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, 0, 0); SDL_RenderPresent(sdlRenderer); } else { sdlShowRect = SetShowRect(hwnd, width, height); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, 0, &sdlShowRect); SDL_RenderPresent(sdlRenderer); } break; case WM_LBUTTONDBLCLK: if (!fullScreen) { windowStyle = GetWindowLong(hwnd, GWL_STYLE); GetWindowRect(hwnd, &windowRect); deskHwnd = GetDesktopWindow(); GetWindowRect(deskHwnd, &deskRect); SetWindowLong(hwnd, GWL_STYLE, WS_CHILD); SetWindowPos(hwnd, HWND_TOP, 0, 0, deskRect.right, deskRect.bottom, SWP_SHOWWINDOW); fullScreen = 1; } else { SetWindowLong(hwnd, GWL_STYLE, windowStyle); MoveWindow(hwnd, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, true); fullScreen = 0; } break; case WM_LBUTTONDOWN: open = 1; SDL_DestroyTexture(sdlTexture); if (!OpenFile(hwnd, fullPath, fileName,&sdlShowRect)) { return -1; } WideCharToMultiByte(CP_UTF8,0, fullPath,-1, u8FullPath, sizeof(u8FullPath),0,0); sdlSurface = IMG_Load(u8FullPath); width = sdlSurface->w; height = sdlSurface->h; sdlShowRect = SetShowRect(hwnd, width, height); sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface); SDL_FreeSurface(sdlSurface); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, 0, &sdlShowRect); SDL_RenderPresent(sdlRenderer); break; case WM_CLOSE: SDL_DestroyTexture(sdlTexture); SDL_DestroyRenderer(sdlRenderer); SDL_DestroyWindow(sdlWindow); DestroyWindow(hwnd); break; case WM_DESTROY: SDL_Quit(); PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
/** \fn init */ bool sdlRenderImpl::init( GUI_WindowInfo * window, uint32_t w, uint32_t h,renderZoom zoom) { ADM_info("[SDL] Initializing video subsystem\n"); int bpp; int flags; baseInit(w,h,zoom); if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { ADM_warning("[SDL] FAILED initialising video subsystem\n"); ADM_warning("[SDL] ERROR: %s\n", SDL_GetError()); return false; } ADM_info("[SDL] Video subsystem init ok\n"); sdl_running=true; ADM_info("[SDL] Creating window (at %x,%d)\n",window->x,window->y); int nbDriver=listOfSDLDrivers.size(); if(!nbDriver) { ADM_warning("[SDL] No driver loaded\n"); return false; } if(sdlDriverIndex==-1 || sdlDriverIndex>=nbDriver) { ADM_warning("[SDL] No available driver found\n"); return false; } #if 0 sdl_window = SDL_CreateWindow("avidemux_sdl2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_BORDERLESS | SDL_WINDOW_FOREIGN*1); SDL_SetWindowPosition(sdl_window,window->x,window->y); #else sdl_window=SDL_CreateWindowFrom((void*)window->systemWindowId); #endif if(!sdl_window) { ADM_info("[SDL] Creating window failed!\n"); ADM_warning("[SDL] ERROR: %s\n", SDL_GetError()); cleanup(); return false; } sdl_renderer = SDL_CreateRenderer(sdl_window, sdlDriverIndex, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if(!sdl_renderer) sdl_renderer = SDL_CreateRenderer(sdl_window, sdlDriverIndex, 0); if(!sdl_renderer) { ADM_warning("[SDL] FAILED to create a renderer\n"); cleanup(); return false; } sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, w, h); if(sdl_texture) { useYV12=true; }else { useYV12=false; sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h); if(!sdl_texture) { ADM_warning("[SDL] FAILED to create a texture (rgb)\n"); cleanup(); return false; } } ADM_info("[SDL] Setting final size\n"); changeZoom(zoom); ADM_info("[SDL] All init done.\n"); return true; }
int InitVideo(FCEUGI *gi) { // This is a big TODO. Stubbing this off into its own function, // as the SDL surface routines have changed drastically in SDL2 // TODO - SDL2 const char * window_name; int error, flags = 0; int doublebuf, xstretch, ystretch, xres, yres, show_fps; uint32_t Amask, Rmask, Gmask, Bmask; int bpp; FCEUI_printf("Initializing video (SDL2.x) ..."); // load the relevant configuration variables g_config->getOption("SDL.Fullscreen", &s_fullscreen); g_config->getOption("SDL.DoubleBuffering", &doublebuf); #ifdef OPENGL g_config->getOption("SDL.OpenGL", &s_useOpenGL); #endif g_config->getOption("SDL.SpecialFilter", &s_sponge); g_config->getOption("SDL.XStretch", &xstretch); g_config->getOption("SDL.YStretch", &ystretch); g_config->getOption("SDL.LastXRes", &xres); g_config->getOption("SDL.LastYRes", &yres); g_config->getOption("SDL.ClipSides", &s_clipSides); g_config->getOption("SDL.NoFrame", &noframe); g_config->getOption("SDL.ShowFPS", &show_fps); // check the starting, ending, and total scan lines FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline); s_tlines = s_erendline - s_srendline + 1; #if OPENGL if( !s_useOpenGL || s_sponge ) { FCEUD_PrintError("SDL2 Does not support non-OpenGL rendering or special filters\n"); KillVideo(); return -1; } #endif // initialize the SDL video subsystem if it is not already active if(!SDL_WasInit(SDL_INIT_VIDEO)) { error = SDL_InitSubSystem(SDL_INIT_VIDEO); if(error) { FCEUD_PrintError(SDL_GetError()); return -1; } } s_inited = 1; // For simplicity, hard-code this to 32bpp for now... s_curbpp = 32; // If game is running, set window name accordingly if( gi ) { window_name = (const char *) gi->name; } else { window_name = "FCE Ultra"; } s_exs = 1.0; s_eys = 1.0; if(s_fullscreen) { s_window = SDL_CreateWindow( window_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, // Res not specified in full-screen mode SDL_WINDOW_FULLSCREEN_DESKTOP); } else { #if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) if(noGui == 0 && strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { s_window = SDL_CreateWindowFrom((void*)GDK_WINDOW_XID (gtk_widget_get_window(evbox))); } else #endif s_window = SDL_CreateWindow( window_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xres, yres, 0); } // This stuff all applies regardless of full-screen vs windowed mode. s_renderer = SDL_CreateRenderer(s_window, -1, 0); // Set logical rendering size & specify scaling mode. All rendering is // now done to the renderer rather than directly to the screen surface. // The renderer takes care of any scaling necessary. // // NOTE: setting scale quality to "nearest" will result in a blown-up but // pixelated while "linear" will tend to blur everything. SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); SDL_RenderSetLogicalSize(s_renderer, xres, yres); // // Create the texture that will ultimately be rendered. // s_screen is used to build up an image, then the texture will be updated // all at once when it's ready s_texture = SDL_CreateTexture(s_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, xres, yres); // // Create a surface to draw pixels onto // SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, &bpp, &Rmask, &Gmask, &Bmask, &Amask); s_screen = SDL_CreateRGBSurface(0, xres, yres, bpp, Rmask, Gmask, Bmask, Amask); if( !s_screen ) { FCEUD_PrintError(SDL_GetError()); return -1; } // // Setup Icon surface // #ifdef LSB_FIRST s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, 32, 32, 24, 32 * 3, 0xFF, 0xFF00, 0xFF0000, 0x00); #else s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, 32, 32, 24, 32 * 3, 0xFF0000, 0xFF00, 0xFF, 0x00); #endif SDL_SetWindowIcon(s_window, s_IconSurface); s_paletterefresh = 1; // Force palette refresh // always init blit to high since bpp forced to 32 for now. InitBlitToHigh(s_curbpp >> 3, s_screen->format->Rmask, s_screen->format->Gmask, s_screen->format->Bmask, 0, //s_eefx, Hard-code SFX off 0, //s_sponge, Hard-code special filters off. 0); return 0; }
// WINDOWS MAIN FUNCTION // hInst = current instance of the program // hPrevInst = previous instance which is not used anymore. // cmdLine = holds command line arguments to be passed in to the program // cmdShow = holds an integer to specify if we want to show this window. int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int cmdShow) { WNDCLASS wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hInstance = hInst; wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = wndClassName; wc.hCursor = 0; //TODO: Add cursors and icons to this program. wc.hIcon = 0; wc.lpfnWndProc = (WNDPROC)wndProc; RegisterClass(&wc); HWND window = CreateWindow(wndClassName, wndTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, wndWidth, wndHeight, 0, 0, hInst, 0); if(window) { ShowWindow(window, SW_SHOW); UpdateWindow(window); // NOTE: Initializing SDL if(SDL_Init(SDL_INIT_VIDEO) != 0 ) { DestroyWindow(window); return -2; } IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG); sdlWindow = SDL_CreateWindowFrom((void*)window); char error[MAX_PATH]; stringCopy(error, SDL_GetError()); OutputDebugStringA(error); if(!sdlWindow) { SDL_Quit(); DestroyWindow(window); return -3; } renderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if(!renderer) { SDL_DestroyWindow(sdlWindow); SDL_Quit(); DestroyWindow(window); return -4; } i32 RefreshRate = 0; HDC dc = GetDC(window); i32 winRefreshRate = GetDeviceCaps(dc, VREFRESH); if( winRefreshRate > 1 ) { RefreshRate = winRefreshRate / 2; } else { RefreshRate = 30; } r32 targetSecsPerFrame = 1.0f / RefreshRate; GameMemory memory = {}; memory.permanentSize = Megabytes(64); memory.transientSize = Megabytes(64); memory.totalSize = memory.permanentSize + memory.transientSize; gameMemoryBlock = VirtualAlloc( 0, memory.totalSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(!gameMemoryBlock) { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(sdlWindow); SDL_Quit(); DestroyWindow(window); return -5; } memory.permanentBlock = gameMemoryBlock; memory.transientBlock = (i8*)gameMemoryBlock + memory.permanentSize; memory.readEntireFile = ReadEntireFile; memory.freeFile = FreeFile; memory.writeEntireFile = WriteEntireFile; Win32Dims windowDims = GetWindowDimensions(window); Render render = {}; render.renderer = renderer; render.screenW = windowDims.width; render.screenH = windowDims.height; GameController input = {0}; input.dt = targetSecsPerFrame; Win32State state = {0}; state.memoryBlock = gameMemoryBlock; state.memorySize = memory.totalSize; GameCodeDLL gameCode = Win32LoadGameCode("Game.dll", "Game_temp.dll", "lock.tmp"); isRunning = true; r32 sleepIsGranular = (timeBeginPeriod(1) == TIMERR_NOERROR); LARGE_INTEGER lastCounter = Win32GetClock(); i64 lastCycles = __rdtsc(); LARGE_INTEGER performanceFreqPerSecRes; QueryPerformanceFrequency(&performanceFreqPerSecRes); globalPerformanceCountFreq = performanceFreqPerSecRes.QuadPart; // NOTE: PROGRAM LOOP!! while(isRunning) { // NOTE: compare File times for us to be able to reload the new game code FILETIME currentFileTime = Win32GetLastWriteTime("Game.dll"); if(CompareFileTime(¤tFileTime, &gameCode.lastWriteTime) != 0) { Win32UnloadGameCode(&gameCode); gameCode = Win32LoadGameCode("Game.dll", "Game_temp.dll", "lock.tmp"); } MSG msg = {0}; while(PeekMessage(&msg, window, 0, 0, PM_REMOVE)) { switch(msg.message) { case WM_CLOSE: { isRunning = false; }break; case WM_KEYUP: case WM_KEYDOWN: case WM_SYSKEYUP: case WM_SYSKEYDOWN: { u32 vkCode = (u32)msg.wParam; // This contains the keycode for the key that the user pressed. bool isDown = ((msg.lParam & (1 << 31)) == 0); // Check to see if the key is down now. bool wasDown = ((msg.lParam & (1 << 30)) != 0); // Check to see if the key was down previously. if(isDown != wasDown) { if(vkCode == 'W') { input.moveUp.isDown = isDown; } else if(vkCode == 'S') { input.moveDown.isDown = isDown; } else if(vkCode == 'A') { input.moveLeft.isDown = isDown; } else if(vkCode == 'D') { input.moveRight.isDown = isDown; } if(vkCode == VK_UP) { input.actionUp.isDown = isDown; } else if(vkCode == VK_DOWN) { input.actionDown.isDown = isDown; } else if(vkCode == VK_LEFT) { input.actionLeft.isDown = isDown; } else if(vkCode == VK_RIGHT) { input.actionRight.isDown = isDown; } else if(vkCode == VK_ESCAPE) { input.back.isDown = isDown; } else if(vkCode == 'O') { if(isDown) { if(state.recordingIndex == 0) { BeginRecording(&state, 1); } else { EndRecording(&state); BeginPlayback(&state, 1); } } } else if(vkCode == 'P') { if(isDown) { if(state.playbackIndex > 0) { EndPlayback(&state); ZeroMemory(&input, sizeof(input)); } } } } if(isDown) { bool AltKeyWasDown = ((msg.lParam & (1 << 29)) != 0); if(vkCode == VK_RETURN && AltKeyWasDown) { if(msg.hwnd) { isFullscreen = !isFullscreen; Win32FullscreenToggle(msg.hwnd); } } } }break; default: { TranslateMessage(&msg); DispatchMessage(&msg); } } } if(input.back.isDown) { isRunning = false; PostQuitMessage(0); } if(state.recordingIndex > 0) { RecordingInput(&state, &input); } else if(state.playbackIndex > 0) { PlaybackInput(&state, &input); } Win32Dims windowDims = GetWindowDimensions(window); Win32UpdateWindow(windowDims, (i32*)&render.screenW, (i32*)&render.screenH); if(gameCode.UpdateRender) { gameCode.UpdateRender(&memory, &input, &render); } LARGE_INTEGER workCounter = Win32GetClock(); r32 workSecsElapsed = Win32GetSecondsElapsed(lastCounter, workCounter); r32 secondsElapsed = workSecsElapsed; if(secondsElapsed < targetSecsPerFrame) { if(sleepIsGranular) { DWORD sleepMS = (DWORD)(1000.0f * (targetSecsPerFrame - secondsElapsed)); if(sleepMS > 0) { Sleep(sleepMS); } } r32 testSecsElapsed = Win32GetSecondsElapsed(lastCounter, Win32GetClock()); if(testSecsElapsed < targetSecsPerFrame) { //TODO: LOG MISSED SLEEP HERE!! } while(secondsElapsed < targetSecsPerFrame) { secondsElapsed = Win32GetSecondsElapsed(lastCounter, Win32GetClock()); } } else { //TODO: MISSED FRAME RATE!! } LARGE_INTEGER endCounter = Win32GetClock(); i64 endCycles = __rdtsc(); r64 elapsedCounts = (r64)(endCounter.QuadPart - lastCounter.QuadPart); r64 elapsedCycles = (r64)(endCycles - lastCycles); r32 MSperFrame = ((1000.0f * Win32GetSecondsElapsed(lastCounter, endCounter))); r32 FPS = (r32)(globalPerformanceCountFreq / elapsedCounts); r32 MegaCyclesPerFrame = (r32)(elapsedCycles / (1000.0f * 1000.0f)); char buffer[256]; sprintf_s(buffer, "%.02fms, %.02ffps, %.02fmcpf\n", MSperFrame, FPS, MegaCyclesPerFrame); OutputDebugStringA(buffer); lastCounter = endCounter; lastCycles = endCycles; } // NOTE: END OF WHILE LOOP //IMPORTANT: Unload this when we exit the program. Win32UnloadGameCode(&gameCode); } else { // TODO: Handle Error Loggin here!! return -1; } if(gameMemoryBlock) { VirtualFree(gameMemoryBlock, 0, MEM_RELEASE); } //Close SDL_DestroyRenderer(renderer); SDL_DestroyWindow(sdlWindow); IMG_Quit(); SDL_Quit(); DestroyWindow(window); return 0; }