int WIN_GL_LoadLibrary(_THIS, const char *path) { LPTSTR wpath; HANDLE handle; if (path == NULL) { path = SDL_getenv("SDL_OPENGL_LIBRARY"); } if (path == NULL) { path = DEFAULT_OPENGL; } wpath = WIN_UTF8ToString(path); _this->gl_config.dll_handle = LoadLibrary(wpath); SDL_free(wpath); if (!_this->gl_config.dll_handle) { char message[1024]; SDL_snprintf(message, SDL_arraysize(message), "LoadLibrary(\"%s\")", path); WIN_SetError(message); return -1; } SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); /* Allocate OpenGL memory */ _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData)); if (!_this->gl_data) { SDL_OutOfMemory(); return -1; } /* Load function pointers */ handle = _this->gl_config.dll_handle; _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *)) GetProcAddress(handle, "wglGetProcAddress"); _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC)) GetProcAddress(handle, "wglCreateContext"); _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC)) GetProcAddress(handle, "wglDeleteContext"); _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC)) GetProcAddress(handle, "wglMakeCurrent"); _this->gl_data->wglSwapIntervalEXT = (void (WINAPI *) (int)) GetProcAddress(handle, "wglSwapIntervalEXT"); _this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *) (void)) GetProcAddress(handle, "wglGetSwapIntervalEXT"); if (!_this->gl_data->wglGetProcAddress || !_this->gl_data->wglCreateContext || !_this->gl_data->wglDeleteContext || !_this->gl_data->wglMakeCurrent) { SDL_SetError("Could not retrieve OpenGL functions"); SDL_UnloadObject(handle); return -1; } return 0; }
SDL_GLContext WIN_GL_CreateContext(_THIS, SDL_Window * window) { HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; HGLRC context, share_context; if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile) { #if SDL_VIDEO_OPENGL_EGL /* Switch to EGL based functions */ WIN_GL_UnloadLibrary(_this); _this->GL_LoadLibrary = WIN_GLES_LoadLibrary; _this->GL_GetProcAddress = WIN_GLES_GetProcAddress; _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; _this->GL_CreateContext = WIN_GLES_CreateContext; _this->GL_MakeCurrent = WIN_GLES_MakeCurrent; _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; _this->GL_SwapWindow = WIN_GLES_SwapWindow; _this->GL_DeleteContext = WIN_GLES_DeleteContext; if (WIN_GLES_LoadLibrary(_this, NULL) != 0) { return NULL; } return WIN_GLES_CreateContext(_this, window); #else SDL_SetError("SDL not configured with EGL support"); return NULL; #endif } if (_this->gl_config.share_with_current_context) { share_context = (HGLRC)SDL_GL_GetCurrentContext(); } else { share_context = 0; } if (_this->gl_config.major_version < 3 && _this->gl_config.profile_mask == 0 && _this->gl_config.flags == 0) { /* Create legacy context */ context = _this->gl_data->wglCreateContext(hdc); if( share_context != 0 ) { _this->gl_data->wglShareLists(share_context, context); } } else { PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; HGLRC temp_context = _this->gl_data->wglCreateContext(hdc); if (!temp_context) { SDL_SetError("Could not create GL context"); return NULL; } /* Make the context current */ if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) { WIN_GL_DeleteContext(_this, temp_context); return NULL; } wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> wglGetProcAddress("wglCreateContextAttribsARB"); if (!wglCreateContextAttribsARB) { SDL_SetError("GL 3.x is not supported"); context = temp_context; } else { /* max 10 attributes plus terminator */ int attribs[11] = { WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; int iattr = 4; /* SDL profile bits match WGL profile bits */ if (_this->gl_config.profile_mask != 0) { attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB; attribs[iattr++] = _this->gl_config.profile_mask; } /* SDL flags match WGL flags */ if (_this->gl_config.flags != 0) { attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB; attribs[iattr++] = _this->gl_config.flags; } /* only set if wgl extension is available */ if (_this->gl_data->HAS_WGL_ARB_context_flush_control) { attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB; attribs[iattr++] = _this->gl_config.release_behavior ? WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB; } attribs[iattr++] = 0; /* Create the GL 3.x context */ context = wglCreateContextAttribsARB(hdc, share_context, attribs); /* Delete the GL 2.x context */ _this->gl_data->wglDeleteContext(temp_context); } } if (!context) { WIN_SetError("Could not create GL context"); return NULL; } if (WIN_GL_MakeCurrent(_this, window, context) < 0) { WIN_GL_DeleteContext(_this, context); return NULL; } return context; }
int WIN_GL_SetupWindow(_THIS, SDL_Window * window) { HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; PIXELFORMATDESCRIPTOR pfd; int pixel_format; int iAttribs[64]; int *iAttr; float fAttribs[1] = { 0 }; WIN_GL_SetupPixelFormat(_this, &pfd); /* setup WGL_ARB_pixel_format attribs */ iAttr = &iAttribs[0]; *iAttr++ = WGL_DRAW_TO_WINDOW_ARB; *iAttr++ = GL_TRUE; *iAttr++ = WGL_RED_BITS_ARB; *iAttr++ = _this->gl_config.red_size; *iAttr++ = WGL_GREEN_BITS_ARB; *iAttr++ = _this->gl_config.green_size; *iAttr++ = WGL_BLUE_BITS_ARB; *iAttr++ = _this->gl_config.blue_size; if (_this->gl_config.alpha_size) { *iAttr++ = WGL_ALPHA_BITS_ARB; *iAttr++ = _this->gl_config.alpha_size; } *iAttr++ = WGL_DOUBLE_BUFFER_ARB; *iAttr++ = _this->gl_config.double_buffer; *iAttr++ = WGL_DEPTH_BITS_ARB; *iAttr++ = _this->gl_config.depth_size; if (_this->gl_config.stencil_size) { *iAttr++ = WGL_STENCIL_BITS_ARB; *iAttr++ = _this->gl_config.stencil_size; } if (_this->gl_config.accum_red_size) { *iAttr++ = WGL_ACCUM_RED_BITS_ARB; *iAttr++ = _this->gl_config.accum_red_size; } if (_this->gl_config.accum_green_size) { *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB; *iAttr++ = _this->gl_config.accum_green_size; } if (_this->gl_config.accum_blue_size) { *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB; *iAttr++ = _this->gl_config.accum_blue_size; } if (_this->gl_config.accum_alpha_size) { *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB; *iAttr++ = _this->gl_config.accum_alpha_size; } if (_this->gl_config.stereo) { *iAttr++ = WGL_STEREO_ARB; *iAttr++ = GL_TRUE; } if (_this->gl_config.multisamplebuffers) { *iAttr++ = WGL_SAMPLE_BUFFERS_ARB; *iAttr++ = _this->gl_config.multisamplebuffers; } if (_this->gl_config.multisamplesamples) { *iAttr++ = WGL_SAMPLES_ARB; *iAttr++ = _this->gl_config.multisamplesamples; } if (_this->gl_config.accelerated >= 0) { *iAttr++ = WGL_ACCELERATION_ARB; *iAttr++ = (_this->gl_config.accelerated ? WGL_FULL_ACCELERATION_ARB : WGL_NO_ACCELERATION_ARB); } *iAttr = 0; /* Choose and set the closest available pixel format */ pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); if (!pixel_format) { pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd); } if (!pixel_format) { SDL_SetError("No matching GL pixel format available"); return -1; } if (!SetPixelFormat(hdc, pixel_format, &pfd)) { WIN_SetError("SetPixelFormat()"); return (-1); } return 0; }
int WIN_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; size_t size; LPBITMAPINFO info; HBITMAP hbm; /* Free the old framebuffer surface */ if (data->mdc) { DeleteDC(data->mdc); } if (data->hbm) { DeleteObject(data->hbm); } /* Find out the format of the screen */ size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD); info = (LPBITMAPINFO)SDL_stack_alloc(Uint8, size); SDL_memset(info, 0, size); info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); /* The second call to GetDIBits() fills in the bitfields */ hbm = CreateCompatibleBitmap(data->hdc, 1, 1); GetDIBits(data->hdc, hbm, 0, 0, NULL, info, DIB_RGB_COLORS); GetDIBits(data->hdc, hbm, 0, 0, NULL, info, DIB_RGB_COLORS); DeleteObject(hbm); *format = SDL_PIXELFORMAT_UNKNOWN; if (info->bmiHeader.biCompression == BI_BITFIELDS) { int bpp; Uint32 *masks; bpp = info->bmiHeader.biPlanes * info->bmiHeader.biBitCount; masks = (Uint32*)((Uint8*)info + info->bmiHeader.biSize); *format = SDL_MasksToPixelFormatEnum(bpp, masks[0], masks[1], masks[2], 0); } if (*format == SDL_PIXELFORMAT_UNKNOWN) { /* We'll use RGB format for now */ *format = SDL_PIXELFORMAT_RGB888; /* Create a new one */ SDL_memset(info, 0, size); info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = 32; info->bmiHeader.biCompression = BI_RGB; } /* Fill in the size information */ *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3); info->bmiHeader.biWidth = window->w; info->bmiHeader.biHeight = -window->h; /* negative for topdown bitmap */ info->bmiHeader.biSizeImage = window->h * (*pitch); data->mdc = CreateCompatibleDC(data->hdc); data->hbm = CreateDIBSection(data->hdc, info, DIB_RGB_COLORS, pixels, NULL, 0); SDL_stack_free(info); if (!data->hbm) { return WIN_SetError("Unable to create DIB"); } SelectObject(data->mdc, data->hbm); return 0; }
/* actual work of WIN_GL_SetupWindow() happens here. */ static int WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window) { HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; PIXELFORMATDESCRIPTOR pfd; int pixel_format = 0; int iAttribs[64]; int *iAttr; int *iAccelAttr; float fAttribs[1] = { 0 }; WIN_GL_SetupPixelFormat(_this, &pfd); /* setup WGL_ARB_pixel_format attribs */ iAttr = &iAttribs[0]; *iAttr++ = WGL_DRAW_TO_WINDOW_ARB; *iAttr++ = GL_TRUE; *iAttr++ = WGL_RED_BITS_ARB; *iAttr++ = _this->gl_config.red_size; *iAttr++ = WGL_GREEN_BITS_ARB; *iAttr++ = _this->gl_config.green_size; *iAttr++ = WGL_BLUE_BITS_ARB; *iAttr++ = _this->gl_config.blue_size; if (_this->gl_config.alpha_size) { *iAttr++ = WGL_ALPHA_BITS_ARB; *iAttr++ = _this->gl_config.alpha_size; } *iAttr++ = WGL_DOUBLE_BUFFER_ARB; *iAttr++ = _this->gl_config.double_buffer; *iAttr++ = WGL_DEPTH_BITS_ARB; *iAttr++ = _this->gl_config.depth_size; if (_this->gl_config.stencil_size) { *iAttr++ = WGL_STENCIL_BITS_ARB; *iAttr++ = _this->gl_config.stencil_size; } if (_this->gl_config.accum_red_size) { *iAttr++ = WGL_ACCUM_RED_BITS_ARB; *iAttr++ = _this->gl_config.accum_red_size; } if (_this->gl_config.accum_green_size) { *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB; *iAttr++ = _this->gl_config.accum_green_size; } if (_this->gl_config.accum_blue_size) { *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB; *iAttr++ = _this->gl_config.accum_blue_size; } if (_this->gl_config.accum_alpha_size) { *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB; *iAttr++ = _this->gl_config.accum_alpha_size; } if (_this->gl_config.stereo) { *iAttr++ = WGL_STEREO_ARB; *iAttr++ = GL_TRUE; } if (_this->gl_config.multisamplebuffers) { *iAttr++ = WGL_SAMPLE_BUFFERS_ARB; *iAttr++ = _this->gl_config.multisamplebuffers; } if (_this->gl_config.multisamplesamples) { *iAttr++ = WGL_SAMPLES_ARB; *iAttr++ = _this->gl_config.multisamplesamples; } if (_this->gl_config.framebuffer_srgb_capable) { *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; *iAttr++ = _this->gl_config.framebuffer_srgb_capable; } /* We always choose either FULL or NO accel on Windows, because of flaky drivers. If the app didn't specify, we use FULL, because that's probably what they wanted (and if you didn't care and got FULL, that's a perfectly valid result in any case). */ *iAttr++ = WGL_ACCELERATION_ARB; iAccelAttr = iAttr; if (_this->gl_config.accelerated) { *iAttr++ = WGL_FULL_ACCELERATION_ARB; } else { *iAttr++ = WGL_NO_ACCELERATION_ARB; } *iAttr = 0; /* Choose and set the closest available pixel format */ pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); /* App said "don't care about accel" and FULL accel failed. Try NO. */ if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) { *iAccelAttr = WGL_NO_ACCELERATION_ARB; pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */ } if (!pixel_format) { pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd); } if (!pixel_format) { return SDL_SetError("No matching GL pixel format available"); } if (!SetPixelFormat(hdc, pixel_format, &pfd)) { return WIN_SetError("SetPixelFormat()"); } return 0; }
static SDL_Cursor * WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) { /* msdn says cursor mask has to be padded out to word alignment. Not sure if that means machine word or WORD, but this handles either case. */ const size_t pad = (sizeof (size_t) * 8); /* 32 or 64, or whatever. */ SDL_Cursor *cursor; HICON hicon; HDC hdc; BITMAPV4HEADER bmh; LPVOID pixels; LPVOID maskbits; size_t maskbitslen; ICONINFO ii; SDL_zero(bmh); bmh.bV4Size = sizeof(bmh); bmh.bV4Width = surface->w; bmh.bV4Height = -surface->h; /* Invert the image */ bmh.bV4Planes = 1; bmh.bV4BitCount = 32; bmh.bV4V4Compression = BI_BITFIELDS; bmh.bV4AlphaMask = 0xFF000000; bmh.bV4RedMask = 0x00FF0000; bmh.bV4GreenMask = 0x0000FF00; bmh.bV4BlueMask = 0x000000FF; maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h; maskbits = SDL_stack_alloc(Uint8,maskbitslen); if (maskbits == NULL) { SDL_OutOfMemory(); return NULL; } /* AND the cursor against full bits: no change. We already have alpha. */ SDL_memset(maskbits, 0xFF, maskbitslen); hdc = GetDC(NULL); SDL_zero(ii); ii.fIcon = FALSE; ii.xHotspot = (DWORD)hot_x; ii.yHotspot = (DWORD)hot_y; ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0); ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits); ReleaseDC(NULL, hdc); SDL_stack_free(maskbits); SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); SDL_assert(surface->pitch == surface->w * 4); SDL_memcpy(pixels, surface->pixels, surface->h * surface->pitch); hicon = CreateIconIndirect(&ii); DeleteObject(ii.hbmColor); DeleteObject(ii.hbmMask); if (!hicon) { WIN_SetError("CreateIconIndirect()"); return NULL; } cursor = SDL_calloc(1, sizeof(*cursor)); if (cursor) { cursor->driverdata = hicon; } else { DestroyIcon(hicon); SDL_OutOfMemory(); } return cursor; }
static int SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_WindowData *data; /* Allocate the window data */ data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data)); if (!data) { return SDL_OutOfMemory(); } data->window = window; data->hwnd = hwnd; data->hdc = GetDC(hwnd); data->created = created; data->mouse_button_flags = 0; data->videodata = videodata; window->driverdata = data; /* Associate the data with the window */ if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) { ReleaseDC(hwnd, data->hdc); SDL_free(data); return WIN_SetError("SetProp() failed"); } /* Set up the window proc function */ #ifdef GWLP_WNDPROC data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC); if (data->wndproc == WIN_WindowProc) { data->wndproc = NULL; } else { SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc); } #else data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC); if (data->wndproc == WIN_WindowProc) { data->wndproc = NULL; } else { SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc); } #endif /* Fill in the SDL window with the window data */ { RECT rect; if (GetClientRect(hwnd, &rect)) { int w = rect.right; int h = rect.bottom; if ((window->w && window->w != w) || (window->h && window->h != h)) { /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */ WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE); } else { window->w = w; window->h = h; } } } { POINT point; point.x = 0; point.y = 0; if (ClientToScreen(hwnd, &point)) { window->x = point.x; window->y = point.y; } } { DWORD style = GetWindowLong(hwnd, GWL_STYLE); if (style & WS_VISIBLE) { window->flags |= SDL_WINDOW_SHOWN; } else { window->flags &= ~SDL_WINDOW_SHOWN; } if (style & (WS_BORDER | WS_THICKFRAME)) { window->flags &= ~SDL_WINDOW_BORDERLESS; } else { window->flags |= SDL_WINDOW_BORDERLESS; } if (style & WS_THICKFRAME) { window->flags |= SDL_WINDOW_RESIZABLE; } else { window->flags &= ~SDL_WINDOW_RESIZABLE; } #ifdef WS_MAXIMIZE if (style & WS_MAXIMIZE) { window->flags |= SDL_WINDOW_MAXIMIZED; } else #endif { window->flags &= ~SDL_WINDOW_MAXIMIZED; } #ifdef WS_MINIMIZE if (style & WS_MINIMIZE) { window->flags |= SDL_WINDOW_MINIMIZED; } else #endif { window->flags &= ~SDL_WINDOW_MINIMIZED; } } if (GetFocus() == hwnd) { window->flags |= SDL_WINDOW_INPUT_FOCUS; SDL_SetKeyboardFocus(data->window); if (window->flags & SDL_WINDOW_INPUT_GRABBED) { RECT rect; GetClientRect(hwnd, &rect); ClientToScreen(hwnd, (LPPOINT) & rect); ClientToScreen(hwnd, (LPPOINT) & rect + 1); ClipCursor(&rect); } } /* Enable multi-touch */ if (videodata->RegisterTouchWindow) { videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM)); } /* Enable dropping files */ DragAcceptFiles(hwnd, TRUE); /* All done! */ return 0; }
SDL_GLContext WIN_GL_CreateContext(_THIS, SDL_Window * window) { HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; HGLRC context, share_context; if (_this->gl_config.share_with_current_context) { share_context = (HGLRC)(_this->current_glctx); } else { share_context = 0; } if (_this->gl_config.major_version < 3 && _this->gl_config.profile_mask == 0 && _this->gl_config.flags == 0) { /* Create legacy context */ context = _this->gl_data->wglCreateContext(hdc); if( share_context != 0 ) { _this->gl_data->wglShareLists(share_context, hdc); } } else { PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; HGLRC temp_context = _this->gl_data->wglCreateContext(hdc); if (!temp_context) { SDL_SetError("Could not create GL context"); return NULL; } /* Make the context current */ if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) { WIN_GL_DeleteContext(_this, temp_context); return NULL; } wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> wglGetProcAddress("wglCreateContextAttribsARB"); if (!wglCreateContextAttribsARB) { SDL_SetError("GL 3.x is not supported"); context = temp_context; } else { /* max 8 attributes plus terminator */ int attribs[9] = { WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; int iattr = 4; /* SDL profile bits match WGL profile bits */ if( _this->gl_config.profile_mask != 0 ) { attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB; attribs[iattr++] = _this->gl_config.profile_mask; } /* SDL flags match WGL flags */ if( _this->gl_config.flags != 0 ) { attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB; attribs[iattr++] = _this->gl_config.flags; } attribs[iattr++] = 0; /* Create the GL 3.x context */ context = wglCreateContextAttribsARB(hdc, share_context, attribs); /* Delete the GL 2.x context */ _this->gl_data->wglDeleteContext(temp_context); } } if (!context) { WIN_SetError("Could not create GL context"); return NULL; } if (WIN_GL_MakeCurrent(_this, window, context) < 0) { WIN_GL_DeleteContext(_this, context); return NULL; } WIN_GL_InitExtensions(_this, hdc); return context; }
int WIN_CreateWindow(_THIS, SDL_Window * window) { HWND hwnd; RECT rect; DWORD style = STYLE_BASIC; int x, y; int w, h; style |= GetWindowStyle(window); /* Figure out what the window area will be */ rect.left = window->x; rect.top = window->y; rect.right = window->x + window->w; rect.bottom = window->y + window->h; AdjustWindowRectEx(&rect, style, FALSE, 0); x = rect.left; y = rect.top; w = (rect.right - rect.left); h = (rect.bottom - rect.top); hwnd = CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL, SDL_Instance, NULL); if (!hwnd) { return WIN_SetError("Couldn't create window"); } WIN_PumpEvents(_this); if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) { DestroyWindow(hwnd); return -1; } #if SDL_VIDEO_OPENGL_WGL /* We need to initialize the extensions before deciding how to create ES profiles */ if (window->flags & SDL_WINDOW_OPENGL) { WIN_GL_InitExtensions(_this); } #endif #if SDL_VIDEO_OPENGL_ES2 if ((window->flags & SDL_WINDOW_OPENGL) && _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES #if SDL_VIDEO_OPENGL_WGL && (!_this->gl_data || !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile) #endif ) { #if SDL_VIDEO_OPENGL_EGL if (WIN_GLES_SetupWindow(_this, window) < 0) { WIN_DestroyWindow(_this, window); return -1; } #else return SDL_SetError("Could not create GLES window surface (no EGL support available)"); #endif /* SDL_VIDEO_OPENGL_EGL */ } else #endif /* SDL_VIDEO_OPENGL_ES2 */ #if SDL_VIDEO_OPENGL_WGL if (window->flags & SDL_WINDOW_OPENGL) { if (WIN_GL_SetupWindow(_this, window) < 0) { WIN_DestroyWindow(_this, window); return -1; } } #endif return 0; }
static int SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_WindowData *data; /* Allocate the window data */ data = (SDL_WindowData *) SDL_malloc(sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } data->window = window; data->hwnd = hwnd; data->hdc = GetDC(hwnd); data->created = created; data->mouse_pressed = SDL_FALSE; data->videodata = videodata; /* Associate the data with the window */ if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) { ReleaseDC(hwnd, data->hdc); SDL_free(data); WIN_SetError("SetProp() failed"); return -1; } /* Set up the window proc function */ #ifdef GWLP_WNDPROC data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC); if (data->wndproc == WIN_WindowProc) { data->wndproc = NULL; } else { SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc); } #else data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC); if (data->wndproc == WIN_WindowProc) { data->wndproc = NULL; } else { SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc); } #endif /* Fill in the SDL window with the window data */ { POINT point; point.x = 0; point.y = 0; if (ClientToScreen(hwnd, &point)) { window->x = point.x; window->y = point.y; } } { RECT rect; if (GetClientRect(hwnd, &rect)) { window->w = rect.right; window->h = rect.bottom; } } { DWORD style = GetWindowLong(hwnd, GWL_STYLE); if (style & WS_VISIBLE) { window->flags |= SDL_WINDOW_SHOWN; } else { window->flags &= ~SDL_WINDOW_SHOWN; } if (style & (WS_BORDER | WS_THICKFRAME)) { window->flags &= ~SDL_WINDOW_BORDERLESS; } else { window->flags |= SDL_WINDOW_BORDERLESS; } if (style & WS_THICKFRAME) { window->flags |= SDL_WINDOW_RESIZABLE; } else { window->flags &= ~SDL_WINDOW_RESIZABLE; } #ifdef WS_MAXIMIZE if (style & WS_MAXIMIZE) { window->flags |= SDL_WINDOW_MAXIMIZED; } else #endif { window->flags &= ~SDL_WINDOW_MAXIMIZED; } #ifdef WS_MINIMIZE if (style & WS_MINIMIZE) { window->flags |= SDL_WINDOW_MINIMIZED; } else #endif { window->flags &= ~SDL_WINDOW_MINIMIZED; } } if (GetFocus() == hwnd) { window->flags |= SDL_WINDOW_INPUT_FOCUS; SDL_SetKeyboardFocus(data->window); if (window->flags & SDL_WINDOW_INPUT_GRABBED) { RECT rect; GetClientRect(hwnd, &rect); ClientToScreen(hwnd, (LPPOINT) & rect); ClientToScreen(hwnd, (LPPOINT) & rect + 1); ClipCursor(&rect); } } /* Enable multi-touch */ if (videodata->RegisterTouchWindow) { videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM)); } /* All done! */ window->driverdata = data; return 0; }
static int GDI_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch) { GDI_TextureData *data = (GDI_TextureData *) texture->driverdata; if (data->yuv) { if (SDL_SW_UpdateYUVTexture(data->yuv, rect, pixels, pitch) < 0) { return -1; } UpdateYUVTextureData(texture); return 0; } else { GDI_RenderData *renderdata = (GDI_RenderData *) renderer->driverdata; if (data->pixels) { Uint8 *src, *dst; int row; size_t length; src = (Uint8 *) pixels; dst = (Uint8 *) data->pixels + rect->y * data->pitch + rect->x * SDL_BYTESPERPIXEL(texture->format); length = rect->w * SDL_BYTESPERPIXEL(texture->format); for (row = 0; row < rect->h; ++row) { SDL_memcpy(dst, src, length); src += pitch; dst += data->pitch; } if (data->premultiplied) { Uint32 *pixels = (Uint32 *) data->pixels + rect->y * (data->pitch / 4) + rect->x; switch (texture->format) { case SDL_PIXELFORMAT_ARGB8888: SDL_PreMultiplyAlphaARGB8888(rect->w, rect->h, pixels, data->pitch); break; case SDL_PIXELFORMAT_RGBA8888: SDL_PreMultiplyAlphaRGBA8888(rect->w, rect->h, pixels, data->pitch); break; case SDL_PIXELFORMAT_ABGR8888: SDL_PreMultiplyAlphaABGR8888(rect->w, rect->h, pixels, data->pitch); break; case SDL_PIXELFORMAT_BGRA8888: SDL_PreMultiplyAlphaBGRA8888(rect->w, rect->h, pixels, data->pitch); break; } } } else if (rect->w == texture->w && pitch == data->pitch) { #ifndef NO_GETDIBBITS if (!SetDIBits (renderdata->window_hdc, data->hbm, rect->y, rect->h, pixels, renderdata->bmi, DIB_RGB_COLORS)) { WIN_SetError("SetDIBits()"); return -1; } #else SDL_SetError("FIXME: Update Texture"); return -1; #endif } else { SDL_SetError ("FIXME: Need to allocate temporary memory and do GetDIBits() followed by SetDIBits(), since we can only set blocks of scanlines at a time"); return -1; } return 0; } }
SDL_Renderer * GDI_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_Renderer *renderer; GDI_RenderData *data; int bmi_size; HBITMAP hbm; int i, n; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (GDI_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { GDI_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } renderer->DisplayModeChanged = GDI_DisplayModeChanged; renderer->CreateTexture = GDI_CreateTexture; renderer->QueryTexturePixels = GDI_QueryTexturePixels; renderer->SetTexturePalette = GDI_SetTexturePalette; renderer->GetTexturePalette = GDI_GetTexturePalette; renderer->SetTextureAlphaMod = GDI_SetTextureAlphaMod; renderer->SetTextureBlendMode = GDI_SetTextureBlendMode; renderer->SetTextureScaleMode = GDI_SetTextureScaleMode; renderer->UpdateTexture = GDI_UpdateTexture; renderer->LockTexture = GDI_LockTexture; renderer->UnlockTexture = GDI_UnlockTexture; renderer->SetDrawBlendMode = GDI_SetDrawBlendMode; renderer->RenderDrawPoints = GDI_RenderDrawPoints; renderer->RenderDrawLines = GDI_RenderDrawLines; renderer->RenderDrawRects = GDI_RenderDrawRects; renderer->RenderFillRects = GDI_RenderFillRects; renderer->RenderCopy = GDI_RenderCopy; renderer->RenderReadPixels = GDI_RenderReadPixels; renderer->RenderWritePixels = GDI_RenderWritePixels; renderer->RenderPresent = GDI_RenderPresent; renderer->DestroyTexture = GDI_DestroyTexture; renderer->DestroyRenderer = GDI_DestroyRenderer; renderer->info = GDI_RenderDriver.info; renderer->window = window; renderer->driverdata = data; renderer->info.flags = SDL_RENDERER_ACCELERATED; data->hwnd = windowdata->hwnd; data->window_hdc = windowdata->hdc; data->render_hdc = CreateCompatibleDC(data->window_hdc); data->memory_hdc = CreateCompatibleDC(data->window_hdc); #ifndef NO_GETDIBBITS /* Fill in the compatible bitmap info */ bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); data->bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size); if (!data->bmi) { GDI_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } data->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); hbm = CreateCompatibleBitmap(data->window_hdc, 1, 1); GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS); GetDIBits(data->window_hdc, hbm, 0, 1, NULL, data->bmi, DIB_RGB_COLORS); DeleteObject(hbm); #endif if (flags & SDL_RENDERER_SINGLEBUFFER) { renderer->info.flags |= (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY); n = 0; } else if (flags & SDL_RENDERER_PRESENTFLIP2) { renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; n = 2; } else if (flags & SDL_RENDERER_PRESENTFLIP3) { renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; n = 3; } else { renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; n = 1; } for (i = 0; i < n; ++i) { data->hbm[i] = CreateCompatibleBitmap(data->window_hdc, window->w, window->h); if (!data->hbm[i]) { GDI_DestroyRenderer(renderer); WIN_SetError("CreateCompatibleBitmap()"); return NULL; } } if (n > 0) { SelectObject(data->render_hdc, data->hbm[0]); data->current_hdc = data->render_hdc; data->makedirty = SDL_TRUE; } else { data->current_hdc = data->window_hdc; data->makedirty = SDL_FALSE; } data->current_hbm = 0; return renderer; }
int WIN_CreateWindow(_THIS, SDL_Window * window) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); RAWINPUTDEVICE Rid; AXIS TabX, TabY; LOGCONTEXTA lc; HWND hwnd; HWND top; RECT rect; SDL_Rect bounds; DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN); int x, y; int w, h; if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) { style |= WS_POPUP; } else { style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); } if ((window->flags & SDL_WINDOW_RESIZABLE) && !(window->flags & SDL_WINDOW_FULLSCREEN)) { style |= (WS_THICKFRAME | WS_MAXIMIZEBOX); } /* Figure out what the window area will be */ if (window->flags & SDL_WINDOW_FULLSCREEN) { top = HWND_TOPMOST; } else { top = HWND_NOTOPMOST; } rect.left = 0; rect.top = 0; rect.right = window->w; rect.bottom = window->h; AdjustWindowRectEx(&rect, style, FALSE, 0); w = (rect.right - rect.left); h = (rect.bottom - rect.top); WIN_GetDisplayBounds(_this, display, &bounds); if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) { x = bounds.x + (bounds.w - window->w) / 2; } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { if (bounds.x == 0) { x = CW_USEDEFAULT; } else { x = bounds.x; } } else { x = bounds.x + window->x + rect.left; } if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) { y = bounds.y + (bounds.h - window->h) / 2; } else if (window->x == SDL_WINDOWPOS_UNDEFINED) { if (bounds.x == 0) { y = CW_USEDEFAULT; } else { y = bounds.y; } } else { y = bounds.y + window->y + rect.top; } hwnd = CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL, SDL_Instance, NULL); if (!hwnd) { WIN_SetError("Couldn't create window"); return -1; } /* we're configuring the tablet data. See Wintab reference for more info */ if (videodata->wintabDLL && videodata->WTInfoA(WTI_DEFSYSCTX, 0, &lc) != 0) { lc.lcPktData = PACKETDATA; lc.lcPktMode = PACKETMODE; lc.lcOptions |= CXO_MESSAGES; lc.lcOptions |= CXO_SYSTEM; lc.lcMoveMask = PACKETDATA; lc.lcBtnDnMask = lc.lcBtnUpMask = PACKETDATA; videodata->WTInfoA(WTI_DEVICES, DVC_X, &TabX); videodata->WTInfoA(WTI_DEVICES, DVC_Y, &TabY); lc.lcInOrgX = 0; lc.lcInOrgY = 0; lc.lcInExtX = TabX.axMax; lc.lcInExtY = TabY.axMax; lc.lcOutOrgX = 0; lc.lcOutOrgY = 0; lc.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); lc.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); if (window->id > highestId) { HCTX *tmp_hctx; highestId = window->id; tmp_hctx = (HCTX *) SDL_realloc(g_hCtx, (highestId + 1) * sizeof(HCTX)); if (!tmp_hctx) { SDL_OutOfMemory(); DestroyWindow(hwnd); return -1; } g_hCtx = tmp_hctx; } g_hCtx[window->id] = videodata->WTOpenA(hwnd, &lc, TRUE); } #ifndef _WIN32_WCE /* has no RawInput */ /* we're telling the window, we want it to report raw input events from mice */ Rid.usUsagePage = 0x01; Rid.usUsage = 0x02; Rid.dwFlags = RIDEV_INPUTSINK; Rid.hwndTarget = hwnd; RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); #endif WIN_PumpEvents(_this); if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) { DestroyWindow(hwnd); return -1; } #ifdef SDL_VIDEO_OPENGL_WGL if (window->flags & SDL_WINDOW_OPENGL) { if (WIN_GL_SetupWindow(_this, window) < 0) { WIN_DestroyWindow(_this, window); return -1; } } #endif return 0; }
int WIN_CreateWindow(_THIS, SDL_Window * window) { HWND hwnd, parent = NULL; DWORD style = STYLE_BASIC; int x, y; int w, h; if (window->flags & SDL_WINDOW_SKIP_TASKBAR) { parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL); } style |= GetWindowStyle(window); /* Figure out what the window area will be */ WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE); hwnd = CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL, SDL_Instance, NULL); if (!hwnd) { return WIN_SetError("Couldn't create window"); } WIN_PumpEvents(_this); if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) { DestroyWindow(hwnd); if (parent) { DestroyWindow(parent); } return -1; } /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */ SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); if (window->flags & SDL_WINDOW_MINIMIZED) { ShowWindow(hwnd, SW_SHOWMINNOACTIVE); } if (!(window->flags & SDL_WINDOW_OPENGL)) { return 0; } /* The rest of this macro mess is for OpenGL or OpenGL ES windows */ #if SDL_VIDEO_OPENGL_ES2 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES #if SDL_VIDEO_OPENGL_WGL && (!_this->gl_data || WIN_GL_UseEGL(_this)) #endif /* SDL_VIDEO_OPENGL_WGL */ ) { #if SDL_VIDEO_OPENGL_EGL if (WIN_GLES_SetupWindow(_this, window) < 0) { WIN_DestroyWindow(_this, window); return -1; } return 0; #else return SDL_SetError("Could not create GLES window surface (EGL support not configured)"); #endif /* SDL_VIDEO_OPENGL_EGL */ } #endif /* SDL_VIDEO_OPENGL_ES2 */ #if SDL_VIDEO_OPENGL_WGL if (WIN_GL_SetupWindow(_this, window) < 0) { WIN_DestroyWindow(_this, window); return -1; } #else return SDL_SetError("Could not create GL window (WGL support not configured)"); #endif return 0; }