• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Main repository of MikuMikuStudio


Commit MetaInfo

Revision7bfd8006751a294d37cad75df61e98dbb73308c6 (tree)
Time2013-07-06 10:37:56
Authorkobayasi <kobayasi@pscn...>
Commiterkobayasi

Log Message

Add FrameBuffer support for Android

Change Summary

Incremental Difference

--- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
+++ b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
@@ -96,7 +96,7 @@ public final class OGLESShaderRenderer implements Renderer {
9696 private int fragUniforms;
9797 private int vertexAttribs;
9898 private int maxFBOSamples;
99- private int maxFBOAttachs;
99+ private int maxFBOAttachs = 1;
100100 private int maxMRTFBOAttachs;
101101 private int maxRBSize;
102102 private int maxTexSize;
@@ -105,6 +105,7 @@ public final class OGLESShaderRenderer implements Renderer {
105105 private int maxTriCount;
106106 private boolean tdc;
107107 private FrameBuffer lastFb = null;
108+ private FrameBuffer mainFbOverride = null;
108109 private final Statistics statistics = new Statistics();
109110 private int vpX, vpY, vpW, vpH;
110111 private int clipX, clipY, clipW, clipH;
@@ -371,6 +372,9 @@ public final class OGLESShaderRenderer implements Renderer {
371372 }
372373 }
373374 */
375+ GLES20.glGetIntegerv(GLES20.GL_MAX_RENDERBUFFER_SIZE, intBuf16);
376+ maxRBSize = intBuf16.get(0);
377+ logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
374378
375379 String extensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
376380 logger.log(Level.INFO, "GL_EXTENSIONS: {0}", extensions);
@@ -885,6 +889,9 @@ public final class OGLESShaderRenderer implements Renderer {
885889 if (val instanceof ColorRGBA) {
886890 ColorRGBA c = (ColorRGBA) val;
887891 GLES20.glUniform4f(loc, c.r, c.g, c.b, c.a);
892+ } else if (val instanceof Vector4f) {
893+ Vector4f c = (Vector4f) val;
894+ GLES20.glUniform4f(loc, c.x, c.y, c.z, c.w);
888895 } else {
889896 Quaternion c = (Quaternion) uniform.getValue();
890897 GLES20.glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW());
@@ -1420,390 +1427,427 @@ public final class OGLESShaderRenderer implements Renderer {
14201427 |* Framebuffers *|
14211428 \*********************************************************************/
14221429 public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
1423- logger.warning("copyFrameBuffer is not supported.");
1430+ copyFrameBuffer(src, dst, true);
14241431 }
14251432
14261433 public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
14271434 logger.warning("copyFrameBuffer is not supported.");
14281435 }
1429- /*
1430- public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
1431- if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){
1432- int srcW = 0;
1433- int srcH = 0;
1434- int dstW = 0;
1435- int dstH = 0;
1436- int prevFBO = context.boundFBO;
1437-
1438- if (src != null && src.isUpdateNeeded())
1439- updateFrameBuffer(src);
1440-
1441- if (dst != null && dst.isUpdateNeeded())
1442- updateFrameBuffer(dst);
1443-
1444- if (src == null){
1445- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
1446- // srcW = viewWidth;
1447- // srcH = viewHeight;
1448- }else{
1449- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
1450- srcW = src.getWidth();
1451- srcH = src.getHeight();
1452- }
1453- if (dst == null){
1454- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
1455- // dstW = viewWidth;
1456- // dstH = viewHeight;
1457- }else{
1458- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
1459- dstW = dst.getWidth();
1460- dstH = dst.getHeight();
1461- }
1462- glBlitFramebufferEXT(0, 0, srcW, srcH,
1463- 0, 0, dstW, dstH,
1464- GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
1465- GL_NEAREST);
1466-
1467- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
1468- try {
1469- checkFrameBufferError();
1470- } catch (IllegalStateException ex){
1471- logger.log(Level.SEVERE, "Source FBO:\n{0}", src);
1472- logger.log(Level.SEVERE, "Dest FBO:\n{0}", dst);
1473- throw ex;
1474- }
1475- }else{
1476- throw new UnsupportedOperationException("EXT_framebuffer_blit required.");
1477- // TODO: support non-blit copies?
1478- }
1436+ private void checkFrameBufferStatus(FrameBuffer fb) {
1437+ try {
1438+ checkFrameBufferError();
1439+ } catch (IllegalStateException ex) {
1440+ logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
1441+ printRealFrameBufferInfo(fb);
1442+ throw ex;
1443+ }
14791444 }
1480- */
14811445
14821446 private void checkFrameBufferError() {
1483- logger.warning("checkFrameBufferError is not supported.");
1447+ int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
1448+ switch (status) {
1449+ case GLES20.GL_FRAMEBUFFER_COMPLETE:
1450+ break;
1451+ case GLES20.GL_FRAMEBUFFER_UNSUPPORTED:
1452+ //Choose different formats
1453+ throw new IllegalStateException("Framebuffer object format is "
1454+ + "unsupported by the video hardware.");
1455+ case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1456+ throw new IllegalStateException("Framebuffer has erronous attachment.");
1457+ case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1458+ throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached.");
1459+ case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1460+ throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
1461+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
1462+// throw new IllegalStateException("Framebuffer attachments must have same formats.");
1463+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
1464+// throw new IllegalStateException("Incomplete draw buffer.");
1465+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1466+// throw new IllegalStateException("Incomplete read buffer.");
1467+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
1468+// throw new IllegalStateException("Incomplete multisample buffer.");
1469+ default:
1470+ //Programming error; will fail on all hardware
1471+ throw new IllegalStateException("Some video driver error "
1472+ + "or programming error occured. "
1473+ + "Framebuffer object status is invalid: " + status);
1474+ }
14841475 }
1485- /*
1486- private void checkFrameBufferError() {
1487- int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1488- switch (status) {
1489- case GL_FRAMEBUFFER_COMPLETE_EXT:
1490- break;
1491- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
1492- //Choose different formats
1493- throw new IllegalStateException("Framebuffer object format is " +
1494- "unsupported by the video hardware.");
1495- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
1496- throw new IllegalStateException("Framebuffer has erronous attachment.");
1497- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
1498- throw new IllegalStateException("Framebuffer is missing required attachment.");
1499- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
1500- throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
1501- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
1502- throw new IllegalStateException("Framebuffer attachments must have same formats.");
1503- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
1504- throw new IllegalStateException("Incomplete draw buffer.");
1505- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1506- throw new IllegalStateException("Incomplete read buffer.");
1507- case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
1508- throw new IllegalStateException("Incomplete multisample buffer.");
1509- default:
1510- //Programming error; will fail on all hardware
1511- throw new IllegalStateException("Some video driver error " +
1512- "or programming error occured. " +
1513- "Framebuffer object status is invalid. ");
1476+ private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) {
1477+ System.out.println("== Renderbuffer " + name + " ==");
1478+ System.out.println("RB ID: " + rb.getId());
1479+ System.out.println("Is proper? " + GLES20.glIsRenderbuffer(rb.getId()));
1480+
1481+ int attachment = convertAttachmentSlot(rb.getSlot());
1482+
1483+ intBuf16.clear();
1484+ GLES20.glGetFramebufferAttachmentParameteriv(GLES20.GL_FRAMEBUFFER,
1485+ attachment, GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16);
1486+ int type = intBuf16.get(0);
1487+
1488+ intBuf16.clear();
1489+ GLES20.glGetFramebufferAttachmentParameteriv(GLES20.GL_FRAMEBUFFER,
1490+ attachment, GLES20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16);
1491+ int rbName = intBuf16.get(0);
1492+
1493+ switch (type) {
1494+ case GLES20.GL_NONE:
1495+ System.out.println("Type: None");
1496+ break;
1497+ case GLES20.GL_TEXTURE:
1498+ System.out.println("Type: Texture");
1499+ break;
1500+ case GLES20.GL_RENDERBUFFER:
1501+ System.out.println("Type: Buffer");
1502+ System.out.println("RB ID: " + rbName);
1503+ break;
1504+ }
1505+
1506+
1507+
15141508 }
1509+
1510+ private void printRealFrameBufferInfo(FrameBuffer fb) {
1511+// boolean doubleBuffer = GLES20.glGetBooleanv(GLES20.GL_DOUBLEBUFFER);
1512+ boolean doubleBuffer = false; // FIXME
1513+// String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER));
1514+// String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
1515+
1516+ int fbId = fb.getId();
1517+ intBuf16.clear();
1518+// int curDrawBinding = GLES20.glGetIntegerv(GLES20.GL_DRAW_FRAMEBUFFER_BINDING);
1519+// int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING);
1520+
1521+ System.out.println("=== OpenGL FBO State ===");
1522+ System.out.println("Context doublebuffered? " + doubleBuffer);
1523+ System.out.println("FBO ID: " + fbId);
1524+ System.out.println("Is proper? " + GLES20.glIsFramebuffer(fbId));
1525+// System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
1526+// System.out.println("Is bound to read? " + (fbId == curReadBinding));
1527+// System.out.println("Draw buffer: " + drawBuf);
1528+// System.out.println("Read buffer: " + readBuf);
1529+
1530+ if (context.boundFBO != fbId) {
1531+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbId);
1532+ context.boundFBO = fbId;
1533+ }
1534+
1535+ if (fb.getDepthBuffer() != null) {
1536+ printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
1537+ }
1538+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1539+ printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
1540+ }
15151541 }
1516- */
15171542
15181543 private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
1519- logger.warning("updateRenderBuffer is not supported.");
1520- }
1521- /*
1522- private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb){
1523- int id = rb.getId();
1524- if (id == -1){
1525- glGenRenderbuffersEXT(intBuf1);
1526- id = intBuf1.get(0);
1527- rb.setId(id);
1528- }
1529-
1530- if (context.boundRB != id){
1531- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id);
1532- context.boundRB = id;
1533- }
1534-
1535- if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize)
1536- throw new UnsupportedOperationException("Resolution "+fb.getWidth()+
1537- ":"+fb.getHeight()+" is not supported.");
1538-
1539- if (fb.getSamples() > 0 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample){
1540- int samples = fb.getSamples();
1541- if (maxFBOSamples < samples){
1542- samples = maxFBOSamples;
1543- }
1544- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
1545- samples,
1546- TextureUtil.convertTextureFormat(rb.getFormat()),
1547- fb.getWidth(),
1548- fb.getHeight());
1549- }else{
1550- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
1551- TextureUtil.convertTextureFormat(rb.getFormat()),
1552- fb.getWidth(),
1553- fb.getHeight());
1554- }
1555- }
1556- */
1544+ int id = rb.getId();
1545+ if (id == -1) {
1546+ GLES20.glGenRenderbuffers(1, intBuf1);
1547+// RendererUtil.checkGLError();
15571548
1558- private int convertAttachmentSlot(int attachmentSlot) {
1559- logger.warning("convertAttachmentSlot is not supported.");
1560- return -1;
1561- }
1562- /*
1563- private int convertAttachmentSlot(int attachmentSlot){
1564- // can also add support for stencil here
1565- if (attachmentSlot == -100){
1566- return GL_DEPTH_ATTACHMENT_EXT;
1567- }else if (attachmentSlot < 0 || attachmentSlot >= 16){
1568- throw new UnsupportedOperationException("Invalid FBO attachment slot: "+attachmentSlot);
1549+ id = intBuf1.get(0);
1550+ rb.setId(id);
1551+ }
1552+
1553+ if (context.boundRB != id) {
1554+ GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, id);
1555+// RendererUtil.checkGLError();
1556+
1557+ context.boundRB = id;
1558+ }
1559+
1560+ if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) {
1561+ throw new RendererException("Resolution " + fb.getWidth()
1562+ + ":" + fb.getHeight() + " is not supported.");
1563+ }
1564+
1565+ TextureUtil.AndroidGLImageFormat imageFormat = TextureUtil.getImageFormat(rb.getFormat());
1566+ if (imageFormat.renderBufferStorageFormat == 0) {
1567+ throw new RendererException("The format '" + rb.getFormat() + "' cannot be used for renderbuffers.");
1568+ }
1569+
1570+// if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
1571+ if (fb.getSamples() > 1) {
1572+// // FIXME
1573+ throw new RendererException("Multisample FrameBuffer is not supported yet.");
1574+// int samples = fb.getSamples();
1575+// if (maxFBOSamples < samples) {
1576+// samples = maxFBOSamples;
1577+// }
1578+// glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
1579+// samples,
1580+// glFmt.internalFormat,
1581+// fb.getWidth(),
1582+// fb.getHeight());
1583+ } else {
1584+ GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
1585+ imageFormat.renderBufferStorageFormat,
1586+ fb.getWidth(),
1587+ fb.getHeight());
1588+
1589+// RendererUtil.checkGLError();
1590+ }
15691591 }
1570-
1571- return GL_COLOR_ATTACHMENT0_EXT + attachmentSlot;
1592+ private int convertAttachmentSlot(int attachmentSlot) {
1593+ // can also add support for stencil here
1594+ if (attachmentSlot == -100) {
1595+ return GLES20.GL_DEPTH_ATTACHMENT;
1596+ } else if (attachmentSlot == 0) {
1597+ return GLES20.GL_COLOR_ATTACHMENT0;
1598+ } else {
1599+ throw new UnsupportedOperationException("Android does not support multiple color attachments to an FBO");
1600+ }
15721601 }
1573- */
15741602
15751603 public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
1576- logger.warning("updateRenderTexture is not supported.");
1577- }
1578- /*
1579- public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb){
1580- Texture tex = rb.getTexture();
1581- Image image = tex.getImage();
1582- if (image.isUpdateNeeded())
1583- updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels());
1584-
1585- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
1586- convertAttachmentSlot(rb.getSlot()),
1587- convertTextureType(tex.getType()),
1588- image.getId(),
1589- 0);
1604+ Texture tex = rb.getTexture();
1605+ Image image = tex.getImage();
1606+ if (image.isUpdateNeeded()) {
1607+ updateTexImageData(image, tex.getType(), false);
1608+
1609+ // NOTE: For depth textures, sets nearest/no-mips mode
1610+ // Required to fix "framebuffer unsupported"
1611+ // for old NVIDIA drivers!
1612+ setupTextureParams(tex);
1613+ }
1614+
1615+ GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
1616+ convertAttachmentSlot(rb.getSlot()),
1617+ convertTextureType(tex.getType()),
1618+ image.getId(),
1619+ 0);
1620+
1621+// RendererUtil.checkGLError();
15901622 }
1591- */
15921623
15931624 public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
1594- logger.warning("updateFrameBufferAttachment is not supported.");
1595- }
1596- /*
1597- public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb){
1598- boolean needAttach;
1599- if (rb.getTexture() == null){
1600- // if it hasn't been created yet, then attach is required.
1601- needAttach = rb.getId() == -1;
1602- updateRenderBuffer(fb, rb);
1603- }else{
1604- needAttach = false;
1605- updateRenderTexture(fb, rb);
1606- }
1607- if (needAttach){
1608- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
1609- convertAttachmentSlot(rb.getSlot()),
1610- GL_RENDERBUFFER_EXT,
1611- rb.getId());
1612- }
1613- }
1614- */
1625+ boolean needAttach;
1626+ if (rb.getTexture() == null) {
1627+ // if it hasn't been created yet, then attach is required.
1628+ needAttach = rb.getId() == -1;
1629+ updateRenderBuffer(fb, rb);
1630+ } else {
1631+ needAttach = false;
1632+ updateRenderTexture(fb, rb);
1633+ }
1634+ if (needAttach) {
1635+ GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
1636+ convertAttachmentSlot(rb.getSlot()),
1637+ GLES20.GL_RENDERBUFFER,
1638+ rb.getId());
16151639
1616- public void updateFrameBuffer(FrameBuffer fb) {
1617- logger.warning("updateFrameBuffer is not supported.");
1640+// RendererUtil.checkGLError();
1641+ }
16181642 }
1619- /*
1643+
16201644 public void updateFrameBuffer(FrameBuffer fb) {
1621- int id = fb.getId();
1622- if (id == -1){
1623- // create FBO
1624- glGenFramebuffersEXT(intBuf1);
1625- id = intBuf1.get(0);
1626- fb.setId(id);
1627- objManager.registerForCleanup(fb);
1628-
1629- statistics.onNewFrameBuffer();
1630- }
1631-
1632- if (context.boundFBO != id){
1633- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
1634- // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
1635- context.boundDrawBuf = 0;
1636- context.boundFBO = id;
1637- }
1638-
1639- FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
1640- if (depthBuf != null){
1641- updateFrameBufferAttachment(fb, depthBuf);
1642- }
1643-
1644- for (int i = 0; i < fb.getNumColorBuffers(); i++){
1645- FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
1646- updateFrameBufferAttachment(fb, colorBuf);
1647- }
1648-
1649- fb.clearUpdateNeeded();
1645+ int id = fb.getId();
1646+ if (id == -1) {
1647+ intBuf1.clear();
1648+ // create FBO
1649+ GLES20.glGenFramebuffers(1, intBuf1);
1650+// RendererUtil.checkGLError();
1651+
1652+ id = intBuf1.get(0);
1653+ fb.setId(id);
1654+ objManager.registerForCleanup(fb);
1655+
1656+ statistics.onNewFrameBuffer();
1657+ }
1658+
1659+ if (context.boundFBO != id) {
1660+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, id);
1661+// RendererUtil.checkGLError();
1662+
1663+ // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
1664+ context.boundDrawBuf = 0;
1665+ context.boundFBO = id;
1666+ }
1667+
1668+ FrameBuffer.RenderBuffer depthBuf = fb.getDepthBuffer();
1669+ if (depthBuf != null) {
1670+ updateFrameBufferAttachment(fb, depthBuf);
1671+ }
1672+
1673+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1674+ FrameBuffer.RenderBuffer colorBuf = fb.getColorBuffer(i);
1675+ updateFrameBufferAttachment(fb, colorBuf);
1676+ }
1677+
1678+ fb.clearUpdateNeeded();
16501679 }
1651- */
16521680
1653- public void setMainFrameBufferOverride(FrameBuffer fb) {
1681+ public void setMainFrameBufferOverride(FrameBuffer fb){
1682+ mainFbOverride = fb;
16541683 }
16551684
16561685 public void setFrameBuffer(FrameBuffer fb) {
1657- if (verboseLogging) {
1658- logger.warning("setFrameBuffer is not supported.");
1686+ if (fb == null && mainFbOverride != null) {
1687+ fb = mainFbOverride;
1688+ }
1689+
1690+ if (lastFb == fb) {
1691+ if (fb == null || !fb.isUpdateNeeded()) {
1692+ return;
1693+ }
1694+ }
1695+
1696+ // generate mipmaps for last FB if needed
1697+ if (lastFb != null) {
1698+ for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
1699+ RenderBuffer rb = lastFb.getColorBuffer(i);
1700+ Texture tex = rb.getTexture();
1701+ if (tex != null
1702+ && tex.getMinFilter().usesMipMapLevels()) {
1703+ setTexture(0, rb.getTexture());
1704+
1705+// int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
1706+ int textureType = convertTextureType(tex.getType());
1707+ GLES20.glGenerateMipmap(textureType);
1708+// RendererUtil.checkGLError();
1709+ }
1710+ }
1711+ }
1712+
1713+ if (fb == null) {
1714+ // unbind any fbos
1715+ if (context.boundFBO != 0) {
1716+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
1717+// RendererUtil.checkGLError();
1718+
1719+ statistics.onFrameBufferUse(null, true);
1720+
1721+ context.boundFBO = 0;
1722+ }
1723+
1724+ /*
1725+ // select back buffer
1726+ if (context.boundDrawBuf != -1) {
1727+ glDrawBuffer(initialDrawBuf);
1728+ context.boundDrawBuf = -1;
1729+ }
1730+ if (context.boundReadBuf != -1) {
1731+ glReadBuffer(initialReadBuf);
1732+ context.boundReadBuf = -1;
1733+ }
1734+ */
1735+
1736+ lastFb = null;
1737+ } else {
1738+ if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
1739+ throw new IllegalArgumentException("The framebuffer: " + fb
1740+ + "\nDoesn't have any color/depth buffers");
1741+ }
1742+
1743+ if (fb.isUpdateNeeded()) {
1744+ updateFrameBuffer(fb);
1745+ }
1746+
1747+ if (context.boundFBO != fb.getId()) {
1748+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb.getId());
1749+// RendererUtil.checkGLError();
1750+
1751+ statistics.onFrameBufferUse(fb, true);
1752+
1753+ // update viewport to reflect framebuffer's resolution
1754+ setViewPort(0, 0, fb.getWidth(), fb.getHeight());
1755+
1756+ context.boundFBO = fb.getId();
1757+ } else {
1758+ statistics.onFrameBufferUse(fb, false);
1759+ }
1760+ if (fb.getNumColorBuffers() == 0) {
1761+// // make sure to select NONE as draw buf
1762+// // no color buffer attached. select NONE
1763+ if (context.boundDrawBuf != -2) {
1764+// glDrawBuffer(GL_NONE);
1765+ context.boundDrawBuf = -2;
1766+ }
1767+ if (context.boundReadBuf != -2) {
1768+// glReadBuffer(GL_NONE);
1769+ context.boundReadBuf = -2;
1770+ }
1771+ } else {
1772+ if (fb.getNumColorBuffers() > maxFBOAttachs) {
1773+ throw new RendererException("Framebuffer has more color "
1774+ + "attachments than are supported"
1775+ + " by the video hardware!");
1776+ }
1777+ if (fb.isMultiTarget()) {
1778+ if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
1779+ throw new RendererException("Framebuffer has more"
1780+ + " multi targets than are supported"
1781+ + " by the video hardware!");
1782+ }
1783+
1784+ if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
1785+ intBuf16.clear();
1786+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1787+ intBuf16.put(GLES20.GL_COLOR_ATTACHMENT0 + i);
1788+ }
1789+
1790+ intBuf16.flip();
1791+// glDrawBuffers(intBuf16);
1792+ context.boundDrawBuf = 100 + fb.getNumColorBuffers();
1793+ }
1794+ } else {
1795+ RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
1796+ // select this draw buffer
1797+ if (context.boundDrawBuf != rb.getSlot()) {
1798+ GLES20.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
1799+// RendererUtil.checkGLError();
1800+
1801+ context.boundDrawBuf = rb.getSlot();
1802+ }
1803+ }
1804+ }
1805+
1806+ assert fb.getId() >= 0;
1807+ assert context.boundFBO == fb.getId();
1808+
1809+ lastFb = fb;
1810+
1811+ checkFrameBufferStatus(fb);
16591812 }
16601813 }
1661- /*
1662- public void setFrameBuffer(FrameBuffer fb) {
1663- if (lastFb == fb)
1664- return;
1665-
1666- // generate mipmaps for last FB if needed
1667- if (lastFb != null){
1668- for (int i = 0; i < lastFb.getNumColorBuffers(); i++){
1669- RenderBuffer rb = lastFb.getColorBuffer(i);
1670- Texture tex = rb.getTexture();
1671- if (tex != null
1672- && tex.getMinFilter().usesMipMapLevels()){
1673- setTexture(0, rb.getTexture());
1674- glGenerateMipmapEXT(convertTextureType(tex.getType()));
1675- }
1676- }
1677- }
1678-
1679-
1680- if (fb == null){
1681- // unbind any fbos
1682- if (context.boundFBO != 0){
1683- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1684- statistics.onFrameBufferUse(null, true);
1685-
1686- context.boundFBO = 0;
1687- }
1688- // select back buffer
1689- if (context.boundDrawBuf != -1){
1690- glDrawBuffer(initialDrawBuf);
1691- context.boundDrawBuf = -1;
1692- }
1693- if (context.boundReadBuf != -1){
1694- glReadBuffer(initialReadBuf);
1695- context.boundReadBuf = -1;
1696- }
1697-
1698- lastFb = null;
1699- }else{
1700- if (fb.isUpdateNeeded())
1701- updateFrameBuffer(fb);
1702-
1703- if (context.boundFBO != fb.getId()){
1704- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb.getId());
1705- statistics.onFrameBufferUse(fb, true);
1706-
1707- // update viewport to reflect framebuffer's resolution
1708- setViewPort(0, 0, fb.getWidth(), fb.getHeight());
1709-
1710- context.boundFBO = fb.getId();
1711- }else{
1712- statistics.onFrameBufferUse(fb, false);
1713- }
1714- if (fb.getNumColorBuffers() == 0){
1715- // make sure to select NONE as draw buf
1716- // no color buffer attached. select NONE
1717- if (context.boundDrawBuf != -2){
1718- glDrawBuffer(GL_NONE);
1719- context.boundDrawBuf = -2;
1720- }
1721- if (context.boundReadBuf != -2){
1722- glReadBuffer(GL_NONE);
1723- context.boundReadBuf = -2;
1724- }
1725- }else{
1726- if (fb.isMultiTarget()){
1727- if (fb.getNumColorBuffers() > maxMRTFBOAttachs)
1728- throw new UnsupportedOperationException("Framebuffer has more"
1729- + " targets than are supported"
1730- + " on the system!");
1731-
1732- if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()){
1733- intBuf16.clear();
1734- for (int i = 0; i < fb.getNumColorBuffers(); i++)
1735- intBuf16.put( GL_COLOR_ATTACHMENT0_EXT + i );
1736-
1737- intBuf16.flip();
1738- glDrawBuffers(intBuf16);
1739- context.boundDrawBuf = 100 + fb.getNumColorBuffers();
1740- }
1741- }else{
1742- RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
1743- // select this draw buffer
1744- if (context.boundDrawBuf != rb.getSlot()){
1745- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
1746- context.boundDrawBuf = rb.getSlot();
1747- }
1748- }
1749- }
1750-
1751- assert fb.getId() >= 0;
1752- assert context.boundFBO == fb.getId();
1753- lastFb = fb;
1754- }
1755-
1756- try {
1757- checkFrameBufferError();
1758- } catch (IllegalStateException ex){
1759- logger.log(Level.SEVERE, "Problem FBO:\n{0}", fb);
1760- throw ex;
1761- }
1762- }
1763- */
17641814
1815+ /**
1816+ * Reads the Color Buffer from OpenGL and stores into the ByteBuffer.
1817+ * Make sure to call setViewPort with the appropriate viewport size before
1818+ * calling readFrameBuffer.
1819+ * @param fb FrameBuffer
1820+ * @param byteBuf ByteBuffer to store the Color Buffer from OpenGL
1821+ */
17651822 public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
1766- logger.warning("readFrameBuffer is not supported.");
1823+ if (fb != null) {
1824+ RenderBuffer rb = fb.getColorBuffer();
1825+ if (rb == null) {
1826+ throw new IllegalArgumentException("Specified framebuffer"
1827+ + " does not have a colorbuffer");
1828+ }
1829+
1830+ setFrameBuffer(fb);
1831+ } else {
1832+ setFrameBuffer(null);
1833+ }
1834+
17671835 GLES20.glReadPixels(vpX, vpY, vpW, vpH, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, byteBuf);
1836+// RendererUtil.checkGLError();
17681837 }
1769- /*
1770- public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf){
1771- if (fb != null){
1772- RenderBuffer rb = fb.getColorBuffer();
1773- if (rb == null)
1774- throw new IllegalArgumentException("Specified framebuffer" +
1775- " does not have a colorbuffer");
1776-
1777- setFrameBuffer(fb);
1778- if (context.boundReadBuf != rb.getSlot()){
1779- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
1780- context.boundReadBuf = rb.getSlot();
1781- }
1782- }else{
1783- setFrameBuffer(null);
1784- }
1785-
1786- glReadPixels(vpX, vpY, vpW, vpH, GL_RGBA GL_BGRA, GL_UNSIGNED_BYTE, byteBuf);
1787- }
1788- */
17891838
17901839 private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
1791- logger.warning("deleteRenderBuffer is not supported.");
17921840 intBuf1.put(0, rb.getId());
17931841 GLES20.glDeleteRenderbuffers(1, intBuf1);
1842+// RendererUtil.checkGLError();
17941843 }
1795- /*
1796- private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb){
1797- intBuf1.put(0, rb.getId());
1798- glDeleteRenderbuffersEXT(intBuf1);
1799- }
1800- */
18011844
18021845 public void deleteFrameBuffer(FrameBuffer fb) {
1803- logger.warning("deleteFrameBuffer is not supported.");
18041846 if (fb.getId() != -1) {
18051847 if (context.boundFBO == fb.getId()) {
18061848 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
1849+// RendererUtil.checkGLError();
1850+
18071851 context.boundFBO = 0;
18081852 }
18091853
@@ -1816,34 +1860,13 @@ public final class OGLESShaderRenderer implements Renderer {
18161860
18171861 intBuf1.put(0, fb.getId());
18181862 GLES20.glDeleteFramebuffers(1, intBuf1);
1863+// RendererUtil.checkGLError();
1864+
18191865 fb.resetObject();
18201866
18211867 statistics.onDeleteFrameBuffer();
18221868 }
18231869 }
1824- /*
1825- public void deleteFrameBuffer(FrameBuffer fb) {
1826- if (fb.getId() != -1){
1827- if (context.boundFBO == fb.getId()){
1828- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1829- context.boundFBO = 0;
1830- }
1831-
1832- if (fb.getDepthBuffer() != null){
1833- deleteRenderBuffer(fb, fb.getDepthBuffer());
1834- }
1835- if (fb.getColorBuffer() != null){
1836- deleteRenderBuffer(fb, fb.getColorBuffer());
1837- }
1838-
1839- intBuf1.put(0, fb.getId());
1840- glDeleteFramebuffersEXT(intBuf1);
1841- fb.resetObject();
1842-
1843- statistics.onDeleteFrameBuffer();
1844- }
1845- }
1846- */
18471870
18481871 /*********************************************************************\
18491872 |* Textures *|
--- a/engine/src/android/com/jme3/renderer/android/TextureUtil.java
+++ b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
@@ -14,6 +14,23 @@ import java.util.logging.Logger;
1414 import javax.microedition.khronos.opengles.GL10;
1515
1616 public class TextureUtil {
17+ public static boolean ENABLE_COMPRESSION = true;
18+ private static boolean NPOT = false;
19+ private static boolean ETC1support = false;
20+ private static boolean DXT1 = false;
21+ private static boolean DEPTH24_STENCIL8 = false;
22+ private static boolean DEPTH_TEXTURE = true;
23+ private static boolean RGBA8 = false;
24+
25+ // Same constant used by both GL_ARM_rgba8 and GL_OES_rgb8_rgba8.
26+ private static final int GL_RGBA8 = 0x8058;
27+
28+ private static final int GL_DXT1 = 0x83F0;
29+ private static final int GL_DXT1A = 0x83F1;
30+
31+ private static final int GL_DEPTH_STENCIL_OES = 0x84F9;
32+ private static final int GL_UNSIGNED_INT_24_8_OES = 0x84FA;
33+ private static final int GL_DEPTH24_STENCIL8_OES = 0x88F0;
1734
1835 public static int convertTextureFormat(Format fmt){
1936 switch (fmt){
@@ -149,7 +166,149 @@ public class TextureUtil {
149166 //bitmap.recycle();
150167 }
151168 }
169+ private static void unsupportedFormat(Format fmt) {
170+ throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware.");
171+ }
172+
173+ public static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
174+ AndroidGLImageFormat imageFormat = new AndroidGLImageFormat();
175+ switch (fmt) {
176+ case RGBA16:
177+ case RGB16:
178+ case RGB10:
179+ case Luminance16:
180+ case Luminance16Alpha16:
181+ case Alpha16:
182+ case Depth32:
183+ case Depth32F:
184+ throw new UnsupportedOperationException("The image format '"
185+ + fmt + "' is not supported by OpenGL ES 2.0 specification.");
186+ case Alpha8:
187+ imageFormat.format = GLES20.GL_ALPHA;
188+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
189+ if (RGBA8) {
190+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
191+ } else {
192+ // Highest precision alpha supported by vanilla OGLES2
193+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
194+ }
195+ break;
196+ case Luminance8:
197+ imageFormat.format = GLES20.GL_LUMINANCE;
198+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
199+ if (RGBA8) {
200+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
201+ } else {
202+ // Highest precision luminance supported by vanilla OGLES2
203+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
204+ }
205+ break;
206+ case Luminance8Alpha8:
207+ imageFormat.format = GLES20.GL_LUMINANCE_ALPHA;
208+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
209+ if (RGBA8) {
210+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
211+ } else {
212+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
213+ }
214+ break;
215+ case RGB565:
216+ imageFormat.format = GLES20.GL_RGB;
217+ imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_6_5;
218+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
219+ break;
220+ case ARGB4444:
221+ imageFormat.format = GLES20.GL_RGBA4;
222+ imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_4_4_4_4;
223+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
224+ break;
225+ case RGB5A1:
226+ imageFormat.format = GLES20.GL_RGBA;
227+ imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_5_5_1;
228+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB5_A1;
229+ break;
230+ case RGB8:
231+ imageFormat.format = GLES20.GL_RGB;
232+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
233+ if (RGBA8) {
234+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
235+ } else {
236+ // Fallback: Use RGB565 if RGBA8 is not available.
237+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
238+ }
239+ break;
240+ case BGR8:
241+ imageFormat.format = GLES20.GL_RGB;
242+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
243+ if (RGBA8) {
244+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
245+ } else {
246+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
247+ }
248+ break;
249+ case RGBA8:
250+ imageFormat.format = GLES20.GL_RGBA;
251+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
252+ if (RGBA8) {
253+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
254+ } else {
255+ imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
256+ }
257+ break;
258+ case Depth:
259+ case Depth16:
260+ if (!DEPTH_TEXTURE) {
261+ unsupportedFormat(fmt);
262+ }
263+ imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
264+ imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
265+ imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
266+ break;
267+ case Depth24:
268+// case Depth24Stencil8:
269+// if (!DEPTH_TEXTURE) {
270+// unsupportedFormat(fmt);
271+// }
272+// if (DEPTH24_STENCIL8) {
273+// // NEW: True Depth24 + Stencil8 format.
274+// imageFormat.format = GL_DEPTH_STENCIL_OES;
275+// imageFormat.dataType = GL_UNSIGNED_INT_24_8_OES;
276+// imageFormat.renderBufferStorageFormat = GL_DEPTH24_STENCIL8_OES;
277+// } else {
278+// // Vanilla OGLES2, only Depth16 available.
279+// imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
280+// imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
281+// imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
282+// }
283+// break;
284+ case DXT1:
285+ if (!DXT1) {
286+ unsupportedFormat(fmt);
287+ }
288+ imageFormat.format = GL_DXT1;
289+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
290+ imageFormat.compress = true;
291+ break;
292+ case DXT1A:
293+ if (!DXT1) {
294+ unsupportedFormat(fmt);
295+ }
296+ imageFormat.format = GL_DXT1A;
297+ imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
298+ imageFormat.compress = true;
299+ break;
300+ default:
301+ throw new UnsupportedOperationException("Unrecognized format: " + fmt);
302+ }
303+ return imageFormat;
304+ }
305+ public static class AndroidGLImageFormat {
152306
307+ boolean compress = false;
308+ int format = -1;
309+ int renderBufferStorageFormat = -1;
310+ int dataType = -1;
311+ }
153312 public static void uploadTexture(
154313 Image img,
155314 int target,