@@ -1358,6 +1358,15 @@ CGSH_OpenGL::BitmapPtr CGSH_OpenGL::FindOrCreateBitmap(const FramebufferPtr& fra
13581358 return sharedPtr;
13591359}
13601360
1361+ CGSH_OpenGL::FramebufferPtr CGSH_OpenGL::FindFramebufferAtPtr (uint32 ptr, uint32 psm) const
1362+ {
1363+ auto framebufferIterator = std::find_if (m_framebuffers.begin (), m_framebuffers.end (),
1364+ [ptr, psm](const FramebufferPtr& framebuffer) {
1365+ return framebuffer->m_psm == psm && framebuffer->m_basePtr == ptr;
1366+ });
1367+ return (framebufferIterator != std::end (m_framebuffers)) ? *(framebufferIterator) : FramebufferPtr ();
1368+ }
1369+
13611370// ///////////////////////////////////////////////////////////
13621371// Individual Primitives Implementations
13631372// ///////////////////////////////////////////////////////////
@@ -1643,6 +1652,15 @@ void CGSH_OpenGL::FlushVertexBuffer()
16431652 }
16441653 DoRenderPass ();
16451654 m_vertexBuffer.clear ();
1655+
1656+ auto handle = m_renderState.framebufferHandle ;
1657+ auto framebufferIterator = std::find_if (m_framebuffers.begin (), m_framebuffers.end (),
1658+ [handle](const FramebufferPtr& framebuffer) {
1659+ return (framebuffer->m_framebuffer == handle);
1660+ });
1661+ const auto & framebuffer = (*framebufferIterator);
1662+
1663+ framebuffer->copiedToRam = false ;
16461664}
16471665
16481666void CGSH_OpenGL::DoRenderPass ()
@@ -1897,6 +1915,90 @@ void CGSH_OpenGL::WriteRegisterImpl(uint8 nRegister, uint64 nData)
18971915 }
18981916}
18991917
1918+ void CGSH_OpenGL::SyncCLUT (const TEX0& tex0)
1919+ {
1920+ if (!ProcessCLD (tex0)) return ;
1921+
1922+ // If we use a CLUT based texture, its possible that the memory
1923+ // referenced is inside a framebuffer. In that case, we need
1924+ // to persist the framebuffer content into the GS RAM.
1925+
1926+ if (CGsPixelFormats::IsPsmIDTEX (tex0.nPsm ))
1927+ {
1928+ const uint32 ptr = tex0.GetCLUTPtr ();
1929+
1930+ FramebufferPtr framebuffer = FindFramebufferAtPtr (ptr, PSMCT32);
1931+ if (framebuffer)
1932+ {
1933+ WriteFramebufferToMemory (framebuffer, true );
1934+ }
1935+ }
1936+
1937+ CGSHandler::SyncCLUT (tex0);
1938+ }
1939+
1940+ void CGSH_OpenGL::WriteFramebufferToMemory (const FramebufferPtr& framebuffer, bool downSample)
1941+ {
1942+ // If the framebuffer has already been persisted to RAM,
1943+ // we don't need to do that again.
1944+ if (framebuffer->copiedToRam )
1945+ {
1946+ return ;
1947+ }
1948+
1949+ FramebufferPtr targetFramebuffer = framebuffer;
1950+ uint32 scale = m_fbScale;
1951+
1952+ if (downSample && m_fbScale != 1 )
1953+ {
1954+ auto dstFramebuffer = FramebufferPtr (new CFramebuffer (
1955+ framebuffer->m_basePtr ,
1956+ framebuffer->m_width ,
1957+ framebuffer->m_height ,
1958+ framebuffer->m_psm ,
1959+ 1 ,
1960+ m_multisampleEnabled));
1961+ PopulateFramebuffer (dstFramebuffer);
1962+
1963+ glBindFramebuffer (GL_FRAMEBUFFER, dstFramebuffer->m_framebuffer );
1964+ glBindFramebuffer (GL_READ_FRAMEBUFFER, framebuffer->m_framebuffer );
1965+
1966+ // Copy buffers
1967+ glBlitFramebuffer (
1968+ 0 , 0 , framebuffer->m_width * m_fbScale, framebuffer->m_height * m_fbScale,
1969+ 0 , 0 , dstFramebuffer->m_width , dstFramebuffer->m_height ,
1970+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
1971+ CHECKGLERROR ();
1972+ glBindFramebuffer (GL_READ_FRAMEBUFFER, 0 );
1973+
1974+ targetFramebuffer = dstFramebuffer;
1975+ scale = 1 ;
1976+ }
1977+
1978+ glBindFramebuffer (GL_FRAMEBUFFER, targetFramebuffer->m_framebuffer );
1979+
1980+ // ----------------------
1981+
1982+ // Read data into ram
1983+
1984+ auto imgbuffer = FindOrCreateBitmap (targetFramebuffer, scale);
1985+ glReadPixels (0 , 0 , targetFramebuffer->m_width * scale, targetFramebuffer->m_height * scale, GL_RGBA, GL_UNSIGNED_BYTE, imgbuffer->GetPixels ());
1986+
1987+ CGsPixelFormats::CPixelIndexorPSMCT32 indexor (m_pRAM, targetFramebuffer->m_basePtr , targetFramebuffer->m_width / 64 );
1988+ for (uint32 y = 0 ; y < targetFramebuffer->m_height ; y++)
1989+ {
1990+ for (uint32 x = 0 ; x < targetFramebuffer->m_width ; x++)
1991+ {
1992+ auto pixel = imgbuffer->GetPixel (x * scale, y * scale);
1993+ indexor.SetPixel (x, y, MakeColor (pixel.r , pixel.g , pixel.b , pixel.a ));
1994+ }
1995+ }
1996+
1997+ framebuffer->copiedToRam = true ;
1998+
1999+ glBindFramebuffer (GL_FRAMEBUFFER, m_renderState.framebufferHandle );
2000+ }
2001+
19002002void CGSH_OpenGL::VertexKick (uint8 nRegister, uint64 nValue)
19012003{
19022004 if (m_nVtxCount == 0 ) return ;
0 commit comments