bool OpenGLRenderVertexBuffer::initialize( ServiceProviderInterface * _serviceProvider, uint32_t _vertexNum, bool _dynamic ) { m_serviceProvider = _serviceProvider; m_memory = Helper::allocateMemory<RenderVertex2D>( _vertexNum ); m_vertexNum = _vertexNum; m_usage = GL_STATIC_DRAW; if( _dynamic == true ) { m_usage = GL_DYNAMIC_DRAW; } GLuint bufId = 0; GLCALL( m_serviceProvider, glGenBuffers, (1, &bufId) ); GLCALL( m_serviceProvider, glBindBuffer, (GL_ARRAY_BUFFER, bufId) ); GLCALL( m_serviceProvider, glBufferData, (GL_ARRAY_BUFFER, m_vertexNum * sizeof( RenderVertex2D ), nullptr, m_usage) ); GLCALL( m_serviceProvider, glBindBuffer, (GL_ARRAY_BUFFER, 0) ); m_id = bufId; return true; }
void OSystem_Android::clearScreen(FixupType type, byte count) { assert(count > 0); bool sm = _show_mouse; _show_mouse = false; GLCALL(glDisable(GL_SCISSOR_TEST)); for (byte i = 0; i < count; ++i) { // clear screen GLCALL(glClearColorx(0, 0, 0, 1 << 16)); GLCALL(glClear(GL_COLOR_BUFFER_BIT)); switch (type) { case kClear: break; case kClearSwap: JNI::swapBuffers(); break; case kClearUpdate: _force_redraw = true; updateScreen(); break; } } if (!_show_overlay) GLCALL(glEnable(GL_SCISSOR_TEST)); _show_mouse = sm; _force_redraw = true; }
void RenderScene::RenderScene(RenderLists* renderLists, Camera* camera) { #ifdef PLATFORM_IOS GLCALL(glGetIntegerv, GL_FRAMEBUFFER_BINDING, &g_default_fbo); #endif GLCALL(glBindFramebuffer, GL_FRAMEBUFFER, SCREEN_FRAME_BUFFER /* default window framebuffer */); renderLists->Draw(camera, false, DISTANCE_FROM_CAMERA_COMPARE_TYPE_ortho_z); }
void Texture::MakeActive(unsigned int slot){ if(slot < GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS){ boundTo = GL_TEXTURE0 + slot; GLCALL(glActiveTexture(boundTo)); GLCALL(glBindTexture(type, buffer)); } }
void OpenGLGraphicsManager::updateScreen() { if (!_gameScreen) { return; } // Clear the screen buffer GLCALL(glClear(GL_COLOR_BUFFER_BIT)); const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); // First step: Draw the (virtual) game screen. _gameScreen->draw(_displayX, _displayY + shakeOffset, _displayWidth, _displayHeight); // Second step: Draw the overlay if visible. if (_overlayVisible) { _overlay->draw(0, 0, _outputScreenWidth, _outputScreenHeight); } // Third step: Draw the cursor if visible. if (_cursorVisible && _cursor) { // Adjust game screen shake position, but only when the overlay is not // visible. const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset; _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled + cursorOffset, _cursorWidthScaled, _cursorHeightScaled); } #ifdef USE_OSD // Fourth step: Draw the OSD. if (_osdAlpha > 0) { Common::StackLock lock(_osdMutex); // Update alpha value. const int diff = g_system->getMillis(false) - _osdFadeStartTime; if (diff > 0) { if (diff >= kOSDFadeOutDuration) { // Back to full transparency. _osdAlpha = 0; } else { // Do a fade out. _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration; } } // Set the OSD transparency. GLCALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f)); // Draw the OSD texture. _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight); // Reset color. GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); } #endif }
void GraphicsComponent::Render(int){ EntitySpecificShaderSetup(); GLCALL(glBindVertexArray(vao_ID)); if(!usesElements){ GLCALL(glDrawArrays(primMode, 0, numElements)); } else{ GLCALL(glDrawElements(primMode, numElements, GL_UNSIGNED_INT, (void*)0)); } GLCALL(glBindVertexArray(0)); }
bool OpenGLRenderVertexBuffer::unlock() { GLCALL( m_serviceProvider, glBindBuffer, (GL_ARRAY_BUFFER, m_id) ); GLCALL( m_serviceProvider, glBufferSubData, (GL_ARRAY_BUFFER, m_lockOffset * sizeof( RenderVertex2D ), m_lockCount * sizeof( RenderVertex2D ), m_lockMemory) ); GLCALL( m_serviceProvider, glBindBuffer, (GL_ARRAY_BUFFER, 0) ); m_lockOffset = 0; m_lockCount = 0; m_lockMemory = nullptr; m_lockFlags = BLF_LOCK_NONE; return true; }
int sage_bind (sageContext *ctx, void *win, int width, int height) { if (hardware < 0) { return -1; } if (ctx == NULL || win == NULL) { if (current != NULL) { /* unbind */ current = NULL; } return 0; } if (ctx == current) { if (win == current->drawable) { /* nop */ return 0; } /* rebind */ } ctx->drawable = win; current = ctx; GLCALL(Viewport)(0, 0, width, height); return 0; }
void OSystem_Android::initViewport() { LOGD("initializing viewport"); assert(JNI::haveSurface()); GLCALL(glDisable(GL_CULL_FACE)); GLCALL(glDisable(GL_DEPTH_TEST)); GLCALL(glEnable(GL_BLEND)); GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height)); LOGD("viewport size: %dx%d", _egl_surface_width, _egl_surface_height); clearFocusRectangle(); }
MarmaladeRenderProgram::~MarmaladeRenderProgram() { if( m_program != 0 ) { GLCALL( m_serviceProvider, glDeleteProgram, (m_program) ); m_program = 0; } }
OpenGLRenderVertexBuffer::~OpenGLRenderVertexBuffer() { if( m_id != 0 ) { GLCALL( m_serviceProvider, glDeleteBuffers, (1, &m_id) ); } Helper::freeMemory( m_memory ); }
void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const { const uint width = _outputScreenWidth; const uint height = _outputScreenHeight; // A line of a BMP image must have a size divisible by 4. // We calculate the padding bytes needed here. // Since we use a 3 byte per pixel mode, we can use width % 4 here, since // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the // usual way of computing the padding bytes required). const uint linePaddingSize = width % 4; const uint lineSize = width * 3 + linePaddingSize; // Allocate memory for screenshot uint8 *pixels = new uint8[lineSize * height]; // Get pixel data from OpenGL buffer GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels)); // BMP stores as BGR. Since we can't assume that GL_BGR is supported we // will swap the components from the RGB we read to BGR on our own. for (uint y = height; y-- > 0;) { uint8 *line = pixels + y * lineSize; for (uint x = width; x > 0; --x, line += 3) { SWAP(line[0], line[2]); } } // Open file Common::DumpFile out; out.open(filename); // Write BMP header out.writeByte('B'); out.writeByte('M'); out.writeUint32LE(height * lineSize + 54); out.writeUint32LE(0); out.writeUint32LE(54); out.writeUint32LE(40); out.writeUint32LE(width); out.writeUint32LE(height); out.writeUint16LE(1); out.writeUint16LE(24); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); // Write pixel data to BMP out.write(pixels, lineSize * height); // Free allocated memory delete[] pixels; }
void Texture::SetStorage(int width, int height, int depth, int levels){ switch(type){ case TT_GL_TEXTURE_1D: GLCALL(glTexStorage1D(type, levels, format, width)); break; case TT_GL_TEXTURE_2D: case TT_GL_TEXTURE_1D_ARRAY: case TT_GL_TEXTURE_RECTANGLE: case TT_GL_TEXTURE_CUBE_MAP: GLCALL(glTexStorage2D(type, levels, format, width, height)); break; case TT_GL_TEXTURE_3D: case TT_GL_TEXTURE_2D_ARRAY: case TT_GL_TEXTURE_CUBE_MAP_ARRAY: GLCALL(glTexStorage3D(type, levels, format, width, height, depth)); break; } }
void GraphicsContext::RenderPass(int pass, ShaderProgram* defaultShader, Camera* cam){ GLCALL(glViewport(0,0, windowWidth, windowHeight)); //Set RenderTarget GLCALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); //Need a constant buffer for Camera shtuff if(cam != NULL) cam->SetCurrent(); if(defaultShader != NULL){ defaultShader->Bind(); defaultShaderForPass = defaultShader; } for( auto it = entitiesPerPass[pass].begin(); it != entitiesPerPass[pass].end(); it++){ (*it)->Render(pass); } if(pass == numPasses-1) SwapBuffers(hdc); }
void OSystem_Android::showOverlay() { ENTER(); _show_overlay = true; _force_redraw = true; updateEventScale(); warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2); GLCALL(glDisable(GL_SCISSOR_TEST)); }
void WaterRenderer::Draw() { ShaderSet* currentShaderSet = FRAMEWORK->GetOpenGLWrapper()->GetCurrentShaderSet(); if (currentShaderSet->HasHandle(SHADER_VARIABLE_VARIABLENAME_scrolling_uv_offset)) { GLint scrolling_uv_offset_handle = currentShaderSet->GetHandle(SHADER_VARIABLE_VARIABLENAME_scrolling_uv_offset); GLCALL(glUniform1f, scrolling_uv_offset_handle, this->scrollingUVsOffset); } if (this->secondaryTexture) { this->secondaryTexture->Draw(2); } MeshRenderer::Draw(); }
void OSystem_Android::hideOverlay() { ENTER(); _show_overlay = false; updateEventScale(); warpMouse(_game_texture->width() / 2, _game_texture->height() / 2); // double buffered, flip twice clearScreen(kClearUpdate, 2); GLCALL(glEnable(GL_SCISSOR_TEST)); }
void MarmaladeRenderProgram::bindTexture( uint32_t _index ) const { if( _index >= m_samplerCount ) { LOGGER_ERROR( m_serviceProvider )("MarmaladeProgram::bindTexture %s invalid support sampler count %d max %d" , m_name.c_str() , _index , m_samplerCount ); return; } int location = m_samplerLocation[_index]; GLCALL( m_serviceProvider, glUniform1i, (location, _index) ); }
void Texture::GiveData(TexData &toGive){ GLCALL(glBindTexture(type, buffer)); switch(type){ case TT_GL_TEXTURE_1D: GLCALL(glTexImage1D(type, toGive.level, format, toGive.width, 0, toGive.format, toGive.type, toGive.data)); break; case TT_GL_TEXTURE_2D: case TT_GL_TEXTURE_1D_ARRAY: case TT_GL_TEXTURE_RECTANGLE: GLCALL(glTexImage2D(type, toGive.level, format, toGive.width, toGive.height, 0, toGive.format, toGive.type, toGive.data)); break; case TT_GL_TEXTURE_CUBE_MAP: GLCALL(glTexImage2D(toGive.target, toGive.level, format, toGive.width, toGive.height, 0, toGive.format, toGive.type, toGive.data)); break; case TT_GL_TEXTURE_3D: case TT_GL_TEXTURE_2D_ARRAY: case TT_GL_TEXTURE_CUBE_MAP_ARRAY: GLCALL(glTexImage3D(type, toGive.level, format, toGive.width, toGive.height, toGive.depth, 0, toGive.format, toGive.type, toGive.data)); break; } GLCALL(glBindTexture(type, 0)); }
void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { // Initialize all extensions. initializeGLExtensions(); // Disable 3D properties. GLCALL(glDisable(GL_CULL_FACE)); GLCALL(glDisable(GL_DEPTH_TEST)); GLCALL(glDisable(GL_LIGHTING)); GLCALL(glDisable(GL_FOG)); GLCALL(glDisable(GL_DITHER)); GLCALL(glShadeModel(GL_FLAT)); GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); // Default to black as clear color. GLCALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); // Setup alpha blend (for overlay and cursor). GLCALL(glEnable(GL_BLEND)); GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); // Enable rendering with vertex and coord arrays. GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); GLCALL(glEnable(GL_TEXTURE_2D)); // We use a "pack" alignment (when reading from textures) to 4 here, // since the only place where we really use it is the BMP screenshot // code and that requires the same alignment too. GLCALL(glPixelStorei(GL_PACK_ALIGNMENT, 4)); // Query information needed by textures. Texture::queryTextureInformation(); // Refresh the output screen dimensions if some are set up. if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { setActualScreenSize(_outputScreenWidth, _outputScreenHeight); } // TODO: Should we try to convert textures into one of those formats if // possible? For example, when _gameScreen is CLUT8 we might want to use // defaultFormat now. _defaultFormat = defaultFormat; _defaultFormatAlpha = defaultFormatAlpha; if (_gameScreen) { _gameScreen->recreateInternalTexture(); } if (_overlay) { _overlay->recreateInternalTexture(); } if (_cursor) { _cursor->recreateInternalTexture(); } #ifdef USE_OSD if (_osd) { _osd->recreateInternalTexture(); } #endif }
void OSystem_Android::updateScreen() { //ENTER(); GLTHREADCHECK; if (!JNI::haveSurface()) return; if (_game_pbuf) { int pitch = _game_texture->width() * _game_texture->getPixelFormat().bytesPerPixel; _game_texture->updateBuffer(0, 0, _game_texture->width(), _game_texture->height(), _game_pbuf.getRawBuffer(), pitch); } if (!_force_redraw && !_game_texture->dirty() && !_overlay_texture->dirty() && !_mouse_texture->dirty()) return; _force_redraw = false; if (_frame_buffer) { _frame_buffer->detach(); glViewport(0,0, _egl_surface_width, _egl_surface_height); } // clear pointer leftovers in dead areas clearScreen(kClear); // TODO this doesnt work on those sucky drivers, do it differently // if (_show_overlay) // GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f)); if (true || _focus_rect.isEmpty()) { _game_texture->drawTextureRect(); drawVirtControls(); } else { // TODO what is this and do we have engines using it? #if 0 GLCALL(glPushMatrix()); GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()), xdiv(_egl_surface_height, _focus_rect.height()), 1 << 16)); GLCALL(glTranslatex(-_focus_rect.left << 16, -_focus_rect.top << 16, 0)); GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width), xdiv(_game_texture->height(), _egl_surface_height), 1 << 16)); _game_texture->drawTextureRect(); GLCALL(glPopMatrix()); #endif } int cs = _mouse_targetscale; if (_show_overlay) { // TODO see above // GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff)); // ugly, but the modern theme sets a wacko factor, only god knows why cs = 1; GLCALL(_overlay_texture->drawTextureRect()); } if (_show_mouse && !_mouse_texture->isEmpty()) { const Common::Point &mouse = getEventManager()->getMousePos(); if (_show_overlay) { _mouse_texture->drawTexture(mouse.x * cs, mouse.y * cs, _mouse_texture->width(), _mouse_texture->height()); } // TODO: Port the non-overlay code as well? #if 0 if (_show_overlay) { } else { const Common::Rect &r = _game_texture->getDrawRect(); GLCALL(glTranslatex(r.left << 16, r.top << 16, 0)); GLCALL(glScalex(xdiv(r.width(), _game_texture->width()), xdiv(r.height(), _game_texture->height()), 1 << 16)); } GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16, (-_mouse_hotspot.y * cs) << 16, 0)); #endif } if (!JNI::swapBuffers()) LOGW("swapBuffers failed: 0x%x", glGetError()); if (_frame_buffer) _frame_buffer->attach(); }
void RenderScene::SetupStuff() { GLCALL(glEnable, GL_DEPTH_TEST); #ifdef PLATFORM_IOS GLCALL(glGetIntegerv, GL_FRAMEBUFFER_BINDING, &g_default_fbo); #endif // Create a frame buffer object: GLCALL(glGenFramebuffers, 1, &g_depth_fbo_id); GLCALL(glBindFramebuffer, GL_FRAMEBUFFER, g_depth_fbo_id); // Create a render buffer GLCALL(glGenRenderbuffers, 1, &renderBuffer); GLCALL(glBindRenderbuffer, GL_RENDERBUFFER, renderBuffer); unsigned int depthMap_width, depthMap_height; ENGINE->GetShadowMap()->GetDepthMapResolution(depthMap_width, depthMap_height); // Create a depth texture: GLCALL(glGenTextures, 1, &ENGINE->GetShadowMap()->depthTexture); GLCALL(glActiveTexture, GL_TEXTURE2); GLCALL(glBindTexture, GL_TEXTURE_2D, ENGINE->GetShadowMap()->depthTexture); GLCALL(glTexImage2D, GL_TEXTURE_2D, 0, GL_RGBA, depthMap_width, depthMap_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // GLCALL(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GLCALL(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLCALL(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); GLCALL(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GLCALL(glFramebufferTexture2D, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ENGINE->GetShadowMap()->depthTexture, 0); // Allocate 16-bit depth buffer GLCALL(glRenderbufferStorage, GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, depthMap_width, depthMap_height); // Attach the render buffer as depth buffer - will be ignored GLCALL(glFramebufferRenderbuffer, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { // GLCALL ASSERT(0, "Framebuffer OK"); } #if MULTISAMPLING_ENABLED //Generate our MSAA Frame and Render buffers glGenFramebuffers(1, &msaaFramebuffer); glGenRenderbuffers(1, &msaaRenderBuffer); //Bind our MSAA buffers glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer); glBindRenderbuffer(GL_RENDERBUFFER, msaaRenderBuffer); unsigned int numSamples = 4; // Generate the msaaDepthBuffer. // numSamples will be the number of pixels that the MSAA buffer will use in order to make one pixel on the render buffer. glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, numSamples, GL_RGB5_A1, FRAMEWORK->GetDeviceProperties()->GetWidthPixels(), FRAMEWORK->GetDeviceProperties()->GetHeightPixels()); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaRenderBuffer); glGenRenderbuffers(1, &msaaDepthBuffer); //Bind the msaa depth buffer. glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBuffer); glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, numSamples, GL_DEPTH_COMPONENT16, FRAMEWORK->GetDeviceProperties()->GetWidthPixels() , FRAMEWORK->GetDeviceProperties()->GetHeightPixels()); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaaDepthBuffer); #endif }
void OSystem_Android::updateScreen() { //ENTER(); GLTHREADCHECK; if (!JNI::haveSurface()) return; if (!_force_redraw && !_game_texture->dirty() && !_overlay_texture->dirty() && !_mouse_texture->dirty()) return; _force_redraw = false; // clear pointer leftovers in dead areas // also, HTC's GLES drivers are made of fail and don't preserve the buffer // ( http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html ) if ((_show_overlay || _htc_fail) && !_fullscreen) clearScreen(kClear); GLCALL(glPushMatrix()); if (_shake_offset != 0 || (!_focus_rect.isEmpty() && !Common::Rect(_game_texture->width(), _game_texture->height()).contains(_focus_rect))) { // These are the only cases where _game_texture doesn't // cover the entire screen. clearScreen(kClear); // Move everything up by _shake_offset (game) pixels GLCALL(glTranslatex(0, -_shake_offset << 16, 0)); } // TODO this doesn't work on those sucky drivers, do it differently // if (_show_overlay) // GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f)); if (_focus_rect.isEmpty()) { _game_texture->drawTextureRect(); } else { GLCALL(glPushMatrix()); GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()), xdiv(_egl_surface_height, _focus_rect.height()), 1 << 16)); GLCALL(glTranslatex(-_focus_rect.left << 16, -_focus_rect.top << 16, 0)); GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width), xdiv(_game_texture->height(), _egl_surface_height), 1 << 16)); _game_texture->drawTextureRect(); GLCALL(glPopMatrix()); } int cs = _mouse_targetscale; if (_show_overlay) { // TODO see above // GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff)); // ugly, but the modern theme sets a wacko factor, only god knows why cs = 1; GLCALL(_overlay_texture->drawTextureRect()); } if (_show_mouse && !_mouse_texture->isEmpty()) { GLCALL(glPushMatrix()); const Common::Point &mouse = getEventManager()->getMousePos(); // Scale up ScummVM -> OpenGL (pixel) coordinates if (_show_overlay) { GLCALL(glScalex(xdiv(_egl_surface_width, _overlay_texture->width()), xdiv(_egl_surface_height, _overlay_texture->height()), 1 << 16)); } else { const Common::Rect &r = _game_texture->getDrawRect(); GLCALL(glTranslatex(r.left << 16, r.top << 16, 0)); GLCALL(glScalex(xdiv(r.width(), _game_texture->width()), xdiv(r.height(), _game_texture->height()), 1 << 16)); } GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16, (-_mouse_hotspot.y * cs) << 16, 0)); // Note the extra half texel to position the mouse in // the middle of the x,y square: GLCALL(glTranslatex((mouse.x << 16) | 1 << 15, (mouse.y << 16) | 1 << 15, 0)); GLCALL(glScalex(cs << 16, cs << 16, 1 << 16)); _mouse_texture->drawTextureOrigin(); GLCALL(glPopMatrix()); } GLCALL(glPopMatrix()); if (!JNI::swapBuffers()) LOGW("swapBuffers failed: 0x%x", glGetError()); }
void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { _outputScreenWidth = width; _outputScreenHeight = height; // Setup coordinates system. GLCALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight)); GLCALL(glMatrixMode(GL_PROJECTION)); GLCALL(glLoadIdentity()); #ifdef USE_GLES GLCALL(glOrthof(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); #else GLCALL(glOrtho(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); #endif GLCALL(glMatrixMode(GL_MODELVIEW)); GLCALL(glLoadIdentity()); uint overlayWidth = width; uint overlayHeight = height; // WORKAROUND: We can only support surfaces up to the maximum supported // texture size. Thus, in case we encounter a physical size bigger than // this maximum texture size we will simply use an overlay as big as // possible and then scale it to the physical display size. This sounds // bad but actually all recent chips should support full HD resolution // anyway. Thus, it should not be a real issue for modern hardware. if ( overlayWidth > (uint)Texture::getMaximumTextureSize() || overlayHeight > (uint)Texture::getMaximumTextureSize()) { const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; if (outputAspect > (frac_t)FRAC_ONE) { overlayWidth = Texture::getMaximumTextureSize(); overlayHeight = intToFrac(overlayWidth) / outputAspect; } else { overlayHeight = Texture::getMaximumTextureSize(); overlayWidth = fracToInt(overlayHeight * outputAspect); } } // HACK: We limit the minimal overlay size to 256x200, which is the // minimum of the dimensions of the two resolutions 256x240 (NES) and // 320x200 (many DOS games use this). This hopefully assure that our // GUI has working layouts. overlayWidth = MAX<uint>(overlayWidth, 256); overlayHeight = MAX<uint>(overlayHeight, 200); if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) { delete _overlay; _overlay = nullptr; _overlay = createTexture(_defaultFormatAlpha); assert(_overlay); // We always filter the overlay with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it // otherwise. _overlay->enableLinearFiltering(true); } _overlay->allocate(overlayWidth, overlayHeight); _overlay->fill(0); #ifdef USE_OSD if (!_osd || _osd->getFormat() != _defaultFormatAlpha) { delete _osd; _osd = nullptr; _osd = createTexture(_defaultFormatAlpha); assert(_osd); // We always filter the osd with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it // otherwise. _osd->enableLinearFiltering(true); } _osd->allocate(_overlay->getWidth(), _overlay->getHeight()); _osd->fill(0); #endif // Re-setup the scaling for the screen and cursor recalculateDisplayArea(); recalculateCursorScaling(); // Something changed, so update the screen change ID. ++_screenChangeID; }
void OSystem_Android::initViewport() { LOGD("initializing viewport"); assert(JNI::haveSurface()); // Turn off anything that looks like 3D ;) GLCALL(glDisable(GL_CULL_FACE)); GLCALL(glDisable(GL_DEPTH_TEST)); GLCALL(glDisable(GL_LIGHTING)); GLCALL(glDisable(GL_FOG)); GLCALL(glDisable(GL_DITHER)); GLCALL(glShadeModel(GL_FLAT)); GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); GLCALL(glEnable(GL_BLEND)); GLCALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); GLCALL(glEnable(GL_TEXTURE_2D)); GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height)); GLCALL(glMatrixMode(GL_PROJECTION)); GLCALL(glLoadIdentity()); GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1)); GLCALL(glMatrixMode(GL_MODELVIEW)); GLCALL(glLoadIdentity()); clearFocusRectangle(); }
bool MarmaladeRenderProgram::initialize( const ConstString & _name, const MarmaladeRenderVertexShaderPtr & _vertexShader, const MarmaladeRenderFragmentShaderPtr & _fragmentShader, uint32_t _samplerCount ) { m_name = _name; m_samplerCount = _samplerCount; if( m_samplerCount > MENGE_MAX_TEXTURE_STAGES ) { LOGGER_ERROR( m_serviceProvider )("MarmaladeProgram::initialize %s don't support sampler count %d max %d" , _name.c_str() , m_samplerCount , MENGE_MAX_TEXTURE_STAGES ); return false; } GLuint program; GLCALLR( m_serviceProvider, program, glCreateProgram, () ); if( program == 0 ) { LOGGER_ERROR( m_serviceProvider )("MarmaladeProgram::initialize %s invalid create program" , _name.c_str() ); return false; } if( _vertexShader != nullptr ) { m_vertexShader = _vertexShader; m_vertexShader->attach( program ); } if( _fragmentShader != nullptr ) { m_fragmentShader = _fragmentShader; m_fragmentShader->attach( program ); } GLCALL( m_serviceProvider, glBindAttribLocation, ( program, VERTEX_POSITION_ARRAY, "inVert" ) ); GLCALL( m_serviceProvider, glBindAttribLocation, ( program, VERTEX_COLOR_ARRAY, "inCol" ) ); for( uint32_t i = 0; i != MENGINE_RENDER_VERTEX_UV_COUNT; ++i ) { char attrib[16]; sprintf( attrib, "inUV%d", i ); GLCALL( m_serviceProvider, glBindAttribLocation, (program, VERTEX_UV0_ARRAY + i, attrib) ); } GLCALL( m_serviceProvider, glLinkProgram, ( program ) ); GLint linked; GLCALL( m_serviceProvider, glGetProgramiv, ( program, GL_LINK_STATUS, &linked ) ); if( linked == GL_FALSE ) { GLchar errorLog[1024] = {0}; GLCALL( m_serviceProvider, glGetProgramInfoLog, ( program, 1023, NULL, errorLog ) ); LOGGER_ERROR( m_serviceProvider )("MarmaladeProgram::shaderProgram - shader linking error '%s'" , errorLog ); return false; } int transformLocation; GLCALLR( m_serviceProvider, transformLocation, glGetUniformLocation, (program, "mvpMat") ); m_transformLocation = transformLocation; for( uint32_t index = 0; index != m_samplerCount; ++index ) { char samplerVar[16]; sprintf( samplerVar, "inSampler%d", index ); int location; GLCALLR( m_serviceProvider, location, glGetUniformLocation, (program, samplerVar) ); m_samplerLocation[index] = location; } m_program = program; return true; }
bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const { #ifdef SCUMM_LITTLE_ENDIAN if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 #else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 #endif glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 glIntFormat = GL_RGB; glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGBA5551 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; return true; #ifndef USE_GLES #ifdef SCUMM_LITTLE_ENDIAN } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_INT_8_8_8_8; return true; #endif } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 // GL_BGRA does not exist in every GLES implementation so should not be configured if // USE_GLES is set. glIntFormat = GL_RGB; glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_1_5_5_5_REV; return true; } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888 glIntFormat = GL_RGBA; glFormat = GL_BGRA; glType = GL_UNSIGNED_INT_8_8_8_8_REV; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444 glIntFormat = GL_RGBA; glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; return true; #ifdef SCUMM_BIG_ENDIAN } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_INT_8_8_8_8_REV; return true; #endif } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888 glIntFormat = GL_RGBA; glFormat = GL_BGRA; glType = GL_UNSIGNED_INT_8_8_8_8; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565 glIntFormat = GL_RGB; glFormat = GL_BGR; glType = GL_UNSIGNED_SHORT_5_6_5; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551 glIntFormat = GL_RGBA; glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_5_5_5_1; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444 glIntFormat = GL_RGBA; glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_4_4_4_4; return true; #endif } else { return false; } } frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const { const uint width = _currentState.gameWidth; const uint height = _currentState.gameHeight; if (_currentState.aspectRatioCorrection) { // In case we enable aspect ratio correction we force a 4/3 ratio. // But just for 320x200 and 640x400 games, since other games do not need // this. if ((width == 320 && height == 200) || (width == 640 && height == 400)) { return intToFrac(4) / 3; } } return intToFrac(width) / height; } void OpenGLGraphicsManager::recalculateDisplayArea() { if (!_gameScreen || _outputScreenHeight == 0) { return; } const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; const frac_t desiredAspect = getDesiredGameScreenAspect(); _displayWidth = _outputScreenWidth; _displayHeight = _outputScreenHeight; // Adjust one dimension for mantaining the aspect ratio. if (outputAspect < desiredAspect) { _displayHeight = intToFrac(_displayWidth) / desiredAspect; } else if (outputAspect > desiredAspect) { _displayWidth = fracToInt(_displayHeight * desiredAspect); } // We center the screen in the middle for now. _displayX = (_outputScreenWidth - _displayWidth ) / 2; _displayY = (_outputScreenHeight - _displayHeight) / 2; } void OpenGLGraphicsManager::updateCursorPalette() { if (!_cursor || !_cursor->hasPalette()) { return; } if (_cursorPaletteEnabled) { _cursor->setPalette(0, 256, _cursorPalette); } else { _cursor->setPalette(0, 256, _gamePalette); } // We remove all alpha bits from the palette entry of the color key. // This makes sure its properly handled as color key. const Graphics::PixelFormat &hardwareFormat = _cursor->getHardwareFormat(); const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift; if (hardwareFormat.bytesPerPixel == 2) { uint16 *palette = (uint16 *)_cursor->getPalette() + _cursorKeyColor; *palette &= ~aMask; } else if (hardwareFormat.bytesPerPixel == 4) { uint32 *palette = (uint32 *)_cursor->getPalette() + _cursorKeyColor; *palette &= ~aMask; } else { warning("OpenGLGraphicsManager::updateCursorPalette: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel); } } void OpenGLGraphicsManager::recalculateCursorScaling() { if (!_cursor || !_gameScreen) { return; } // By default we use the unscaled versions. _cursorHotspotXScaled = _cursorHotspotX; _cursorHotspotYScaled = _cursorHotspotY; _cursorWidthScaled = _cursor->getWidth(); _cursorHeightScaled = _cursor->getHeight(); // In case scaling is actually enabled we will scale the cursor according // to the game screen. if (!_cursorDontScale) { const frac_t screenScaleFactorX = intToFrac(_displayWidth) / _gameScreen->getWidth(); const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight(); _cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX); _cursorWidthScaled = fracToInt(_cursorWidthScaled * screenScaleFactorX); _cursorHotspotYScaled = fracToInt(_cursorHotspotYScaled * screenScaleFactorY); _cursorHeightScaled = fracToInt(_cursorHeightScaled * screenScaleFactorY); } } #ifdef USE_OSD const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont); } #endif void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const { const uint width = _outputScreenWidth; const uint height = _outputScreenHeight; // A line of a BMP image must have a size divisible by 4. // We calculate the padding bytes needed here. // Since we use a 3 byte per pixel mode, we can use width % 4 here, since // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the // usual way of computing the padding bytes required). const uint linePaddingSize = width % 4; const uint lineSize = width * 3 + linePaddingSize; // Allocate memory for screenshot uint8 *pixels = new uint8[lineSize * height]; // Get pixel data from OpenGL buffer GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels)); // BMP stores as BGR. Since we can't assume that GL_BGR is supported we // will swap the components from the RGB we read to BGR on our own. for (uint y = height; y-- > 0;) { uint8 *line = pixels + y * lineSize; for (uint x = width; x > 0; --x, line += 3) { SWAP(line[0], line[2]); } } // Open file Common::DumpFile out; out.open(filename); // Write BMP header out.writeByte('B'); out.writeByte('M'); out.writeUint32LE(height * lineSize + 54); out.writeUint32LE(0); out.writeUint32LE(54); out.writeUint32LE(40); out.writeUint32LE(width); out.writeUint32LE(height); out.writeUint16LE(1); out.writeUint16LE(24); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); out.writeUint32LE(0); // Write pixel data to BMP out.write(pixels, lineSize * height); // Free allocated memory delete[] pixels; } } // End of namespace OpenGL
void MarmaladeRenderProgram::bindMatrix( const mt::mat4f & _worldMatrix, const mt::mat4f & _viewMatrix, const mt::mat4f & _projectionMatrix ) const { m_mvpMat = _worldMatrix * _viewMatrix * _projectionMatrix; GLCALL( m_serviceProvider, glUniformMatrix4fv, (m_transformLocation, 1, GL_FALSE, m_mvpMat.buff()) ); }
void MarmaladeRenderProgram::disable() const { GLCALL( m_serviceProvider, glUseProgram, (0) ); }
void MarmaladeRenderProgram::enable() const { GLCALL( m_serviceProvider, glUseProgram, (m_program) ); }