Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c8977c906 | ||
|
|
6b3cc2e2f3 | ||
|
|
76b2edd6ea | ||
|
|
8ebb37d011 | ||
|
|
3366db83ef | ||
|
|
861d69ea7c | ||
|
|
5415254aac | ||
|
|
b2cc904fab | ||
|
|
3f87b520bb | ||
|
|
135a362176 | ||
|
|
391ebc3702 | ||
|
|
b4d1443720 | ||
|
|
c06737aca2 | ||
|
|
f847232296 | ||
|
|
89f06b8923 | ||
|
|
90a2b1f3c9 | ||
|
|
059f51338d | ||
|
|
d3cea5121e | ||
|
|
c37301d2dc | ||
|
|
aa16778fbd | ||
|
|
ee499ad2ca | ||
|
|
958dd5bb27 | ||
|
|
f988b75999 | ||
|
|
e3ccb4bb3c | ||
|
|
3f0dc6f7e6 | ||
|
|
c212dd5bc7 | ||
|
|
1eceab0040 | ||
|
|
ab9d1e5956 | ||
|
|
c906290416 | ||
|
|
d52a24b6e9 | ||
|
|
9aeec3a759 | ||
|
|
550fcfe2e3 | ||
|
|
b2cdf9f2b4 | ||
|
|
19a3fe3dce | ||
|
|
754abbf78e | ||
|
|
9b855e9a03 | ||
|
|
2534fdf92d | ||
|
|
dab02e915e | ||
|
|
68da1a25eb | ||
|
|
c67b363576 | ||
|
|
5c0e7d8211 | ||
|
|
caacc61602 | ||
|
|
e902df19b2 | ||
|
|
3d57c60840 | ||
|
|
8ab2725a79 | ||
|
|
ff27f8109c | ||
|
|
40b372dda7 | ||
|
|
8e09d8bd71 | ||
|
|
d6df4cd03a | ||
|
|
df03fdf3d7 | ||
|
|
6c59945395 | ||
|
|
d16cc50561 | ||
|
|
fd330a98aa | ||
|
|
e667484a94 | ||
|
|
71e5e6c6c0 | ||
|
|
c1df902593 | ||
|
|
3c3320a2ba | ||
|
|
35753bc6c2 | ||
|
|
5f7967d09c | ||
|
|
404b6e8af3 | ||
|
|
898c20e584 | ||
|
|
f278b76b04 | ||
|
|
6353f17635 | ||
|
|
9cae34babf | ||
|
|
c37cc61b30 | ||
|
|
9aced8e9b8 | ||
|
|
dde060bf4d | ||
|
|
b60518caa5 | ||
|
|
69000ef1f2 | ||
|
|
39d6106ef2 | ||
|
|
96a1cbe69f | ||
|
|
5710304114 | ||
|
|
09fe495384 | ||
|
|
8457d6092d | ||
|
|
72c16e07ed | ||
|
|
12b96cba04 | ||
|
|
e4d943e942 | ||
|
|
7fa66325f3 | ||
|
|
e188a7875e | ||
|
|
ac9822b8c8 | ||
|
|
edb5fddd03 | ||
|
|
35f4a97e32 | ||
|
|
487b10fdda | ||
|
|
271cda88aa | ||
|
|
25b73ddcfa | ||
|
|
35b8146a87 | ||
|
|
091e5a33ac | ||
|
|
ffe4b7390d | ||
|
|
604d3e34a4 | ||
|
|
e116dd4aec | ||
|
|
d53614fb0a | ||
|
|
c91e5df117 | ||
|
|
96574816b3 | ||
|
|
b43a609ebc |
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@@ -50,8 +50,7 @@ jobs:
|
||||
cd build/$WORKFLOW_OS && printf "y" | ./build.sh release
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
pip3 install PyGithub
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
if [ -f out/filament-release-darwin.tgz ]; then mv out/filament-release-darwin.tgz out/filament-${TAG}-mac.tgz; fi;
|
||||
if [ -f out/filament-release-linux.tgz ]; then mv out/filament-release-linux.tgz out/filament-${TAG}-linux.tgz; fi;
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
@@ -80,8 +79,7 @@ jobs:
|
||||
cd build/web && printf "y" | ./build.sh release
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
pip3 install PyGithub
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
mv out/filament-release-web.tgz out/filament-${TAG}-web.tgz
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
env:
|
||||
@@ -123,8 +121,7 @@ jobs:
|
||||
APK_KEYSTORE_PASS: ${{ secrets.APK_KEYSTORE_PASS }}
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
pip3 install PyGithub
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
mv out/filament-android-release.aar out/filament-${TAG}-android.aar
|
||||
mv out/filamat-android-release.aar out/filamat-${TAG}-android.aar
|
||||
mv out/filamat-android-lite-release.aar out/filamat-${TAG}-lite-android.aar
|
||||
@@ -157,8 +154,7 @@ jobs:
|
||||
cd build/ios && printf "y" | ./build.sh release
|
||||
- name: Upload release assets
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
pip3 install PyGithub
|
||||
xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
mv out/filament-release-ios.tgz out/filament-${TAG}-ios.tgz
|
||||
python3 build/common/upload-assets.py ${TAG} out/*.tgz
|
||||
env:
|
||||
|
||||
@@ -647,12 +647,14 @@ add_subdirectory(${LIBRARIES}/gltfio)
|
||||
add_subdirectory(${LIBRARIES}/ibl)
|
||||
add_subdirectory(${LIBRARIES}/iblprefilter)
|
||||
add_subdirectory(${LIBRARIES}/image)
|
||||
add_subdirectory(${LIBRARIES}/ktxreader)
|
||||
add_subdirectory(${LIBRARIES}/math)
|
||||
add_subdirectory(${LIBRARIES}/mathio)
|
||||
add_subdirectory(${LIBRARIES}/utils)
|
||||
add_subdirectory(${LIBRARIES}/viewer)
|
||||
add_subdirectory(${FILAMENT}/filament)
|
||||
add_subdirectory(${FILAMENT}/shaders)
|
||||
add_subdirectory(${EXTERNAL}/basisu/tnt)
|
||||
add_subdirectory(${EXTERNAL}/civetweb/tnt)
|
||||
add_subdirectory(${EXTERNAL}/hat-trie/tnt)
|
||||
add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
@@ -705,8 +707,6 @@ if (IS_HOST_PLATFORM)
|
||||
|
||||
add_subdirectory(${FILAMENT}/samples)
|
||||
|
||||
add_subdirectory(${EXTERNAL}/astcenc/tnt)
|
||||
add_subdirectory(${EXTERNAL}/etc2comp)
|
||||
add_subdirectory(${EXTERNAL}/libassimp/tnt)
|
||||
add_subdirectory(${EXTERNAL}/libpng/tnt)
|
||||
add_subdirectory(${EXTERNAL}/libsdl2/tnt)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.21.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.21.3'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```
|
||||
pod 'Filament', '~> 1.21.0'
|
||||
pod 'Filament', '~> 1.21.3'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -3,9 +3,33 @@
|
||||
This file contains one line summaries of commits that are worthy of mentioning in release notes.
|
||||
A new header is inserted each time a *tag* is created.
|
||||
|
||||
## v1.21.1 (currently main branch)
|
||||
## v1.21.3 (currently main branch)
|
||||
|
||||
- engine: allow both screen-space refraction and screen-space reflections on the same object [⚠️ **Material breakage**].
|
||||
- Java: Renamed the `KTXLoader` Kotlin class to `KTX1Loader`. [⚠️ **API Change**].
|
||||
- libs: Added `Ktx2Reader` and `BasisEncoder` to support Basis-encoded KTX2 files.
|
||||
- engine: Remove deprecated `Stream` APIs, see `Texture::import()` for an alternative [⚠️ **API Change**].
|
||||
- tools: Removed KTX1 compression support from mipgen. [⚠️ **API Change**].
|
||||
- tools: Added support for KTX2 to mipgen.
|
||||
- gltfio: Added `resetBoneMatrices()` method.
|
||||
- gltfio: Introduced `TextureProvider` interface. [⚠️ **API Change**].
|
||||
- gltfio: Fix progress indicator when error occurs.
|
||||
- samples: Desktop and Web Suzanne samples now use KTX2 instead of KTX1.
|
||||
- samples: Fix regression with sample-gltf-viewer and zip files.
|
||||
|
||||
## v1.21.2
|
||||
|
||||
- Java: Add Java binding to get skins in `FilamentAsset`.
|
||||
- libs: Add libs/ktxreader [⚠️ **API Change**].
|
||||
- mipgen: fixups / clarification regarding sRGB.
|
||||
- WebGL: fix intermittent 'detached ArrayBuffer' errors.
|
||||
|
||||
## v1.21.1
|
||||
|
||||
- engine: Allow both screen-space refraction and screen-space reflections on the same object [⚠️ **Material breakage**].
|
||||
- engine: Optimizations for screen-space reflections.
|
||||
- engine: Remove `Viewport::scale()` [⚠️ **API Change**].
|
||||
- engine: Fix 12x overallocation of memory in `MorphTargetBuffer`.
|
||||
- Metal: Fix validation error when reading from default `SwapChain`.
|
||||
|
||||
## v1.21.0
|
||||
|
||||
@@ -440,7 +464,7 @@ devices.
|
||||
- engine: Fix RenderTarget NPE when depth is not present.
|
||||
- engine: Improvements to Camera APIs. Move focus distance from DofOptions to Camera.
|
||||
- engine: VSM shadows now support `shadowMultiplier`.
|
||||
- java: Expose severla MaterialInstance APIs (setColorWrite, setDepthWrite, setDepthCulling) that
|
||||
- java: Expose several MaterialInstance APIs (setColorWrite, setDepthWrite, setDepthCulling) that
|
||||
should have been public.
|
||||
- java: fix bug with Texture::setImage buffer size calculation.
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
// com.google.android.filament.exclude-vulkan
|
||||
// When set, support for Vulkan will be excluded.
|
||||
//
|
||||
// com.google.android.filament.matdbg
|
||||
// When set, enables matdbg, disables shader optimizations
|
||||
//
|
||||
// com.google.android.filament.skip-samples
|
||||
// Exclude samples from the project. Useful to speed up compilation.
|
||||
//
|
||||
@@ -59,6 +62,11 @@ buildscript {
|
||||
.forUseAtConfigurationTime()
|
||||
.isPresent()
|
||||
|
||||
def matdbg = providers
|
||||
.gradleProperty("com.google.android.filament.matdbg")
|
||||
.forUseAtConfigurationTime()
|
||||
.isPresent()
|
||||
|
||||
def abis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
|
||||
def newAbis = providers
|
||||
.gradleProperty("com.google.android.filament.abis")
|
||||
@@ -102,7 +110,9 @@ buildscript {
|
||||
"-DANDROID_PLATFORM=21",
|
||||
"-DANDROID_STL=c++_static",
|
||||
"-DFILAMENT_DIST_DIR=${filamentPath}".toString(),
|
||||
"-DFILAMENT_SUPPORTS_VULKAN=${excludeVulkan ? 'OFF' : 'ON'}".toString()
|
||||
"-DFILAMENT_SUPPORTS_VULKAN=${excludeVulkan ? 'OFF' : 'ON'}".toString(),
|
||||
"-DFILAMENT_ENABLE_MATDBG=${matdbg ? 'ON' : 'OFF'}".toString(),
|
||||
"-DFILAMENT_DISABLE_MATOPT=${matdbg ? 'ON' : 'OFF'}".toString()
|
||||
]
|
||||
|
||||
ext.cppFlags = [
|
||||
|
||||
@@ -133,7 +133,7 @@ public class MaterialBuilder {
|
||||
FADE, // material is transparent and color is alpha-pre-multiplied,
|
||||
// affects specular lighting
|
||||
MULTIPLY, // material darkens what's behind it
|
||||
SCREN // material brightens what's behind it
|
||||
SCREEN // material brightens what's behind it
|
||||
}
|
||||
|
||||
public enum VertexDomain {
|
||||
|
||||
@@ -98,16 +98,6 @@ Java_com_google_android_filament_Stream_nBuilderStreamSource(JNIEnv* env,
|
||||
builder->setStreamSource(env, streamSource);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Stream_nBuilderStream(JNIEnv*, jclass,
|
||||
jlong nativeStreamBuilder, jlong externalTextureId) {
|
||||
StreamBuilder* builder = (StreamBuilder*) nativeStreamBuilder;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
builder->builder()->stream(externalTextureId);
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_Stream_nBuilderWidth(JNIEnv*, jclass,
|
||||
jlong nativeStreamBuilder, jint width) {
|
||||
@@ -143,41 +133,6 @@ Java_com_google_android_filament_Stream_nSetDimensions(JNIEnv*, jclass, jlong na
|
||||
stream->setDimensions((uint32_t) width, (uint32_t) height);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Stream_nReadPixels(JNIEnv *env, jclass,
|
||||
jlong nativeStream, jlong nativeEngine,
|
||||
jint xoffset, jint yoffset, jint width, jint height,
|
||||
jobject storage, jint remaining,
|
||||
jint left, jint top, jint type, jint alignment, jint stride, jint format,
|
||||
jobject handler, jobject runnable) {
|
||||
Stream *stream = (Stream *) nativeStream;
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
|
||||
stride = stride ? stride : width;
|
||||
size_t sizeInBytes = PixelBufferDescriptor::computeDataSize(
|
||||
(PixelDataFormat) format, (PixelDataType) type,
|
||||
(size_t) stride, (size_t) (height + top), (size_t) alignment);
|
||||
|
||||
AutoBuffer nioBuffer(env, storage, 0);
|
||||
if (sizeInBytes > (remaining << nioBuffer.getShift())) {
|
||||
// BufferOverflowException
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buffer = nioBuffer.getData();
|
||||
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
stream->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
|
||||
std::move(desc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_Stream_nGetTimestamp(JNIEnv*, jclass, jlong nativeStream) {
|
||||
Stream *stream = (Stream *) nativeStream;
|
||||
|
||||
@@ -531,6 +531,10 @@ public class Renderer {
|
||||
* Typically, this will happen after multiple calls to {@link #beginFrame},
|
||||
* {@link #render}, {@link #endFrame}.</p>
|
||||
* <br>
|
||||
* <p>OpenGL only: if issuing a <code>readPixels</code> on a {@link RenderTarget} backed by a
|
||||
* {@link Texture} that had data uploaded to it via {@link Texture#setImage}, the data returned
|
||||
* from <code>readPixels</code> will be y-flipped with respect to the {@link Texture#setImage}
|
||||
* call.</p>
|
||||
* <p><code>readPixels</code> is intended for debugging and testing.
|
||||
* It will impact performance significantly.</p>
|
||||
*
|
||||
|
||||
@@ -103,9 +103,6 @@ public class Stream {
|
||||
/** Not synchronized but copy-free. Good for video. */
|
||||
NATIVE,
|
||||
|
||||
/** Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26. */
|
||||
TEXTURE_ID,
|
||||
|
||||
/** Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+. */
|
||||
ACQUIRED,
|
||||
};
|
||||
@@ -121,7 +118,7 @@ public class Stream {
|
||||
* By default, Stream objects are {@link StreamType#ACQUIRED ACQUIRED} and must have external images pushed to them via
|
||||
* {@link #setAcquiredImage}.
|
||||
*
|
||||
* To create a {@link StreamType#NATIVE NATIVE} or {@link StreamType#TEXTURE_ID TEXTURE_ID} stream, call one of the <pre>stream</pre> methods
|
||||
* To create a {@link StreamType#NATIVE NATIVE} stream, call one of the <pre>stream</pre> methods
|
||||
* on the builder.
|
||||
*/
|
||||
public static class Builder {
|
||||
@@ -156,27 +153,6 @@ public class Stream {
|
||||
throw new IllegalArgumentException("Invalid stream source: " + streamSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link StreamType#TEXTURE_ID TEXTURE_ID} stream. A copy stream will sample data from the supplied
|
||||
* external texture and copy it into an internal private texture.
|
||||
*
|
||||
* <p>Currently only OpenGL external texture ids are supported.</p>
|
||||
*
|
||||
* @param externalTextureId An opaque texture id (typically a GLuint created with
|
||||
* <code>glGenTextures()</code>) in a context shared with
|
||||
* filament -- in that case this texture's target must be
|
||||
* <code>GL_TEXTURE_EXTERNAL_OES.</code>
|
||||
* @return This Builder, for chaining calls.
|
||||
* @see Texture#setExternalStream
|
||||
* @deprecated this method existed only for ARCore which doesn't need this anymore, use {@link Texture.Builder#importTexture(long)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NonNull
|
||||
public Builder stream(long externalTextureId) {
|
||||
nBuilderStream(mNativeBuilder, externalTextureId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param width initial width of the incoming stream. Whether this value is used is
|
||||
* stream dependent. On Android, it must be set when using
|
||||
@@ -276,92 +252,6 @@ public class Stream {
|
||||
nSetDimensions(getNativeObject(), width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads back the content of the last frame of a <code>Stream</code> since the last call to
|
||||
* {@link Renderer#beginFrame}.
|
||||
*
|
||||
* <p>The Stream must be a copy stream, which can be checked with {@link #getStreamType()}.
|
||||
* This function is a no-op otherwise.</p>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* Stream buffer User buffer (PixelBufferDescriptor)
|
||||
* +--------------------+
|
||||
* | | .stride .alignment
|
||||
* | | ----------------------->-->
|
||||
* | | O----------------------+--+ low addresses
|
||||
* | | | | | |
|
||||
* | w | | | .top | |
|
||||
* | <---------> | | V | |
|
||||
* | +---------+ | | +---------+ | |
|
||||
* | | ^ | | ======> | | | | |
|
||||
* | x | h| | | |.left| | | |
|
||||
* +------>| v | | +---->| | | |
|
||||
* | +.........+ | | +.........+ | |
|
||||
* | ^ | | | |
|
||||
* | y | | +----------------------+--+ high addresses
|
||||
* O------------+-------+
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* <p>Typically readPixels() will be called after {@link Renderer#beginFrame}.</p>
|
||||
*
|
||||
* <p>After calling this method, the callback associated with <code>buffer</code>
|
||||
* will be invoked on the main thread, indicating that the read-back has completed.
|
||||
* Typically, this will happen after multiple calls to {@link Renderer#beginFrame},
|
||||
* {@link Renderer#render}, {@link Renderer#endFrame}.</p>
|
||||
*
|
||||
* <p><code>readPixels</code> is intended for debugging and testing.
|
||||
* It will impact performance significantly.</p>
|
||||
*
|
||||
* @param xoffset left offset of the sub-region to read back
|
||||
* @param yoffset bottom offset of the sub-region to read back
|
||||
* @param width width of the sub-region to read back
|
||||
* @param height height of the sub-region to read back
|
||||
* @param buffer client-side buffer where the read-back will be written
|
||||
*
|
||||
* <p>
|
||||
* The following format are always supported:
|
||||
* <li>{@link Texture.Format#RGBA}</li>
|
||||
* <li>{@link Texture.Format#RGBA_INTEGER}</li>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The following types are always supported:
|
||||
* <li>{@link Texture.Type#UBYTE}</li>
|
||||
* <li>{@link Texture.Type#UINT}</li>
|
||||
* <li>{@link Texture.Type#INT}</li>
|
||||
* <li>{@link Texture.Type#FLOAT}</li>
|
||||
* </p>
|
||||
*
|
||||
* <p>Other combination of format/type may be supported. If a combination is
|
||||
* not supported, this operation may fail silently. Use a DEBUG build
|
||||
* to get some logs about the failure.</p>
|
||||
*
|
||||
* @exception BufferOverflowException if the specified parameters would result in reading
|
||||
* outside of <code>buffer</code>.
|
||||
*/
|
||||
public void readPixels(
|
||||
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
|
||||
@IntRange(from = 0) int width, @IntRange(from = 0) int height,
|
||||
@NonNull Texture.PixelBufferDescriptor buffer) {
|
||||
|
||||
if (buffer.storage.isReadOnly()) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
|
||||
int result = nReadPixels(getNativeObject(), mNativeEngine,
|
||||
xoffset, yoffset, width, height,
|
||||
buffer.storage, buffer.storage.remaining(),
|
||||
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
|
||||
buffer.stride, buffer.format.ordinal(),
|
||||
buffer.handler, buffer.callback);
|
||||
|
||||
if (result < 0) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the presentation time of the currently displayed frame in nanosecond.
|
||||
*
|
||||
@@ -387,7 +277,6 @@ public class Stream {
|
||||
private static native long nCreateBuilder();
|
||||
private static native void nDestroyBuilder(long nativeStreamBuilder);
|
||||
private static native void nBuilderStreamSource(long nativeStreamBuilder, Object streamSource);
|
||||
private static native void nBuilderStream(long nativeStreamBuilder, long externalTextureId);
|
||||
private static native void nBuilderWidth(long nativeStreamBuilder, int width);
|
||||
private static native void nBuilderHeight(long nativeStreamBuilder, int height);
|
||||
private static native long nBuilderBuild(long nativeStreamBuilder, long nativeEngine);
|
||||
|
||||
@@ -14,6 +14,10 @@ add_library(image STATIC IMPORTED)
|
||||
set_target_properties(image PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libimage.a)
|
||||
|
||||
add_library(ktxreader STATIC IMPORTED)
|
||||
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
|
||||
|
||||
add_library(viewer STATIC IMPORTED)
|
||||
set_target_properties(viewer PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libviewer.a)
|
||||
@@ -64,5 +68,6 @@ target_link_libraries(filament-utils-jni
|
||||
camutils
|
||||
iblprefilter
|
||||
image
|
||||
ktxreader
|
||||
viewer
|
||||
)
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
#include <filament/IndirectLight.h>
|
||||
#include <filament/Skybox.h>
|
||||
|
||||
#include <image/KtxUtility.h>
|
||||
#include <ktxreader/Ktx1Reader.h>
|
||||
|
||||
#include "common/NioUtils.h"
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::math;
|
||||
using namespace image;
|
||||
using namespace ktxreader;
|
||||
|
||||
jlong nCreateHDRTexture(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jint internalFormat);
|
||||
@@ -35,9 +36,9 @@ static jlong nCreateKTXTexture(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
return (jlong) ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
KtxBundle* bundle = (KtxBundle*) userdata;
|
||||
Ktx1Bundle* bundle = new Ktx1Bundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
return (jlong) Ktx1Reader::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
Ktx1Bundle* bundle = (Ktx1Bundle*) userdata;
|
||||
delete bundle;
|
||||
}, bundle);
|
||||
}
|
||||
@@ -46,9 +47,9 @@ static jlong nCreateIndirectLight(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
KtxBundle* bundle = (KtxBundle*) userdata;
|
||||
Ktx1Bundle* bundle = new Ktx1Bundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Texture* cubemap = Ktx1Reader::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
Ktx1Bundle* bundle = (Ktx1Bundle*) userdata;
|
||||
delete bundle;
|
||||
}, bundle);
|
||||
|
||||
@@ -68,9 +69,9 @@ static jlong nCreateSkybox(JNIEnv* env, jclass,
|
||||
jlong nativeEngine, jobject javaBuffer, jint remaining, jboolean srgb) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle* bundle = new KtxBundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Texture* cubemap = ktx::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
KtxBundle* bundle = (KtxBundle*) userdata;
|
||||
Ktx1Bundle* bundle = new Ktx1Bundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Texture* cubemap = Ktx1Reader::createTexture(engine, *bundle, srgb, [](void* userdata) {
|
||||
Ktx1Bundle* bundle = (Ktx1Bundle*) userdata;
|
||||
delete bundle;
|
||||
}, bundle);
|
||||
return (jlong) Skybox::Builder().environment(cubemap).showSun(true).build(*engine);
|
||||
@@ -79,7 +80,7 @@ static jlong nCreateSkybox(JNIEnv* env, jclass,
|
||||
static jboolean nGetSphericalHarmonics(JNIEnv* env, jclass, jobject javaBuffer, jint remaining,
|
||||
jfloatArray outSphericalHarmonics_) {
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
KtxBundle bundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
Ktx1Bundle bundle((const uint8_t*) buffer.getData(), buffer.getSize());
|
||||
|
||||
jfloat* outSphericalHarmonics = env->GetFloatArrayElements(outSphericalHarmonics_, nullptr);
|
||||
const auto success = bundle.getSphericalHarmonics(
|
||||
@@ -98,8 +99,8 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
|
||||
|
||||
int rc;
|
||||
|
||||
// KTXLoader
|
||||
jclass ktxloaderClass = env->FindClass("com/google/android/filament/utils/KTXLoader");
|
||||
// KTX1Loader
|
||||
jclass ktxloaderClass = env->FindClass("com/google/android/filament/utils/KTX1Loader");
|
||||
if (ktxloaderClass == nullptr) return JNI_ERR;
|
||||
static const JNINativeMethod ktxMethods[] = {
|
||||
{(char*)"nCreateKTXTexture", (char*)"(JLjava/nio/Buffer;IZ)J", reinterpret_cast<void*>(nCreateKTXTexture)},
|
||||
|
||||
@@ -40,7 +40,7 @@ import com.google.android.filament.Renderer;
|
||||
*
|
||||
* When executing a test, clients should call tick() after each frame is rendered, which provides an
|
||||
* opportunity to push settings to Filament, increment the current test index (if enough time has
|
||||
* elapsed), and request an asychronous screenshot.
|
||||
* elapsed), and request an asynchronous screenshot.
|
||||
*
|
||||
* The time to sleep between tests is configurable and can be set to zero. Automation also waits a
|
||||
* specified minimum number of frames between tests.
|
||||
|
||||
@@ -24,12 +24,12 @@ import com.google.android.filament.Texture
|
||||
import java.nio.Buffer
|
||||
|
||||
/**
|
||||
* Utilities for consuming KTX files and producing Filament textures, IBLs, and sky boxes.
|
||||
* Utilities for consuming KTX1 files and producing Filament textures, IBLs, and sky boxes.
|
||||
*
|
||||
* KTX is a simple container format that makes it easy to bundle miplevels and cubemap faces
|
||||
* into a single file.
|
||||
*/
|
||||
object KTXLoader {
|
||||
object KTX1Loader {
|
||||
class Options {
|
||||
var srgb = false
|
||||
}
|
||||
@@ -11,6 +11,10 @@ add_library(dracodec STATIC IMPORTED)
|
||||
set_target_properties(dracodec PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libdracodec.a)
|
||||
|
||||
add_library(stb STATIC IMPORTED)
|
||||
set_target_properties(stb PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libstb.a)
|
||||
|
||||
add_library(utils STATIC IMPORTED)
|
||||
set_target_properties(utils PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libutils.a)
|
||||
@@ -32,6 +36,7 @@ set(GLTFIO_SRCS
|
||||
${GLTFIO_DIR}/include/gltfio/ResourceLoader.h
|
||||
${GLTFIO_DIR}/include/gltfio/FilamentAsset.h
|
||||
${GLTFIO_DIR}/include/gltfio/FilamentInstance.h
|
||||
${GLTFIO_DIR}/include/gltfio/TextureProvider.h
|
||||
${GLTFIO_DIR}/include/gltfio/math.h
|
||||
|
||||
${GLTFIO_DIR}/src/Animator.cpp
|
||||
@@ -47,13 +52,13 @@ set(GLTFIO_SRCS
|
||||
${GLTFIO_DIR}/src/GltfEnums.h
|
||||
${GLTFIO_DIR}/src/MaterialProvider.cpp
|
||||
${GLTFIO_DIR}/src/ResourceLoader.cpp
|
||||
${GLTFIO_DIR}/src/StbProvider.cpp
|
||||
${GLTFIO_DIR}/src/TangentsJob.h
|
||||
${GLTFIO_DIR}/src/TangentsJob.cpp
|
||||
${GLTFIO_DIR}/src/UbershaderLoader.cpp
|
||||
${GLTFIO_DIR}/src/Wireframe.cpp
|
||||
${GLTFIO_DIR}/src/Wireframe.h
|
||||
${GLTFIO_DIR}/src/upcast.h
|
||||
${GLTFIO_DIR}/src/Image.cpp
|
||||
|
||||
src/main/cpp/Animator.cpp
|
||||
src/main/cpp/AssetLoader.cpp
|
||||
@@ -90,9 +95,9 @@ set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_
|
||||
|
||||
if(GLTFIO_LITE)
|
||||
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_LITE=1)
|
||||
target_link_libraries(gltfio-jni filament-jni utils log gltfio_resources_lite)
|
||||
target_link_libraries(gltfio-jni filament-jni utils log stb gltfio_resources_lite)
|
||||
else()
|
||||
target_link_libraries(gltfio-jni filament-jni utils log gltfio_resources)
|
||||
target_link_libraries(gltfio-jni filament-jni utils log stb gltfio_resources)
|
||||
|
||||
# Enable Draco in the non-lite variant of gltfio.
|
||||
target_link_libraries(gltfio-jni dracodec)
|
||||
|
||||
@@ -36,6 +36,12 @@ Java_com_google_android_filament_gltfio_Animator_nUpdateBoneMatrices(JNIEnv*, jc
|
||||
animator->updateBoneMatrices();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_Animator_nResetBoneMatrices(JNIEnv*, jclass, jlong nativeAnimator) {
|
||||
Animator* animator = (Animator*) nativeAnimator;
|
||||
animator->resetBoneMatrices();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_Animator_nGetAnimationCount(JNIEnv*, jclass, jlong nativeAnimator) {
|
||||
Animator* animator = (Animator*) nativeAnimator;
|
||||
|
||||
@@ -201,6 +201,44 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetExtras(JNIEnv* env, jc
|
||||
return val ? env->NewStringUTF(val) : nullptr;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinCount(JNIEnv* , jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return (jint) asset->getSkinCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinNames(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jobjectArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
for (int i = 0; i < available; ++i) {
|
||||
const char* name = asset->getSkinNameAt(i);
|
||||
if (name) {
|
||||
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointCountAt(JNIEnv* , jclass,
|
||||
jlong nativeAsset, jint skinIndex) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return (jint) asset->getJointCountAt(skinIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointsAt(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jint skinIndex, jintArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
|
||||
std::copy_n(asset->getJointsAt(skinIndex),
|
||||
std::min(available, (jsize) asset->getJointCountAt(skinIndex)), entities);
|
||||
env->ReleaseIntArrayElements(result, (jint*) entities, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetAnimator(JNIEnv* , jclass,
|
||||
jlong nativeAsset) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <filament/Engine.h>
|
||||
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
#include <gltfio/TextureProvider.h>
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
@@ -114,3 +115,27 @@ Java_com_google_android_filament_gltfio_ResourceLoader_nAsyncCancelLoad(JNIEnv*,
|
||||
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
|
||||
loader->asyncCancelLoad();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateTextureProvider(JNIEnv*, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) createStbProvider(engine);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nDestroyTextureProvider(JNIEnv*, jclass,
|
||||
jlong nativeProvider) {
|
||||
TextureProvider* provider = (TextureProvider*) nativeProvider;
|
||||
delete provider;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nAddTextureProvider(JNIEnv* env, jclass,
|
||||
jlong nativeLoader, jstring url, jlong nativeProvider) {
|
||||
ResourceLoader* loader = (ResourceLoader*) nativeLoader;
|
||||
TextureProvider* provider = (TextureProvider*) nativeProvider;
|
||||
const char* cstring = env->GetStringUTFChars(url, nullptr);
|
||||
loader->addTextureProvider(cstring, provider);
|
||||
env->ReleaseStringUTFChars(url, cstring);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,15 @@ public class Animator {
|
||||
nUpdateBoneMatrices(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the identity matrix into all bone nodes, useful for returning to the T pose.
|
||||
*
|
||||
* <p>NOTE: this operation is independent of <code>animation</code>.</p>
|
||||
*/
|
||||
public void resetBoneMatrices() {
|
||||
nResetBoneMatrices(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of <code>animation</code> definitions in the glTF asset.
|
||||
*/
|
||||
@@ -109,6 +118,7 @@ public class Animator {
|
||||
|
||||
private static native void nApplyAnimation(long nativeAnimator, int index, float time);
|
||||
private static native void nUpdateBoneMatrices(long nativeAnimator);
|
||||
private static native void nResetBoneMatrices(long nativeAnimator);
|
||||
private static native int nGetAnimationCount(long nativeAnimator);
|
||||
private static native float nGetAnimationDuration(long nativeAnimator, int index);
|
||||
private static native String nGetAnimationName(long nativeAnimator, int index);
|
||||
|
||||
@@ -216,6 +216,38 @@ public class FilamentAsset {
|
||||
return mAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin count of this asset.
|
||||
*/
|
||||
public int getSkinCount() {
|
||||
return nGetSkinCount(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin name at skin index in this asset.
|
||||
*/
|
||||
public @NonNull String[] getSkinNames() {
|
||||
String[] result = new String[getSkinCount()];
|
||||
nGetSkinNames(getNativeObject(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the joint count at skin index in this asset.
|
||||
*/
|
||||
public int getJointCountAt(int skinIndex) {
|
||||
return nGetJointCountAt(getNativeObject(), skinIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets joints at skin index in this asset.
|
||||
*/
|
||||
public @NonNull @Entity int[] getJointsAt(int skinIndex) {
|
||||
int[] result = new int[getJointCountAt(skinIndex)];
|
||||
nGetJointsAt(getNativeObject(), skinIndex, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of all morph targets in the given entity.
|
||||
*/
|
||||
@@ -306,6 +338,10 @@ public class FilamentAsset {
|
||||
private static native String nGetExtras(long nativeAsset, int entity);
|
||||
private static native long nGetAnimator(long nativeAsset);
|
||||
private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
|
||||
private static native int nGetSkinCount(long nativeAsset);
|
||||
private static native void nGetSkinNames(long nativeAsset, String[] result);
|
||||
private static native int nGetJointCountAt(long nativeAsset, int skinIndex);
|
||||
private static native void nGetJointsAt(long nativeAsset, int skinIndex, int[] result);
|
||||
private static native int nGetResourceUriCount(long nativeAsset);
|
||||
private static native void nGetResourceUris(long nativeAsset, String[] result);
|
||||
private static native void nReleaseSourceData(long nativeAsset);
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.nio.Buffer;
|
||||
*/
|
||||
public class ResourceLoader {
|
||||
private final long mNativeObject;
|
||||
private final long mNativeProvider;
|
||||
|
||||
/**
|
||||
* Constructs a resource loader tied to the given Filament engine.
|
||||
@@ -46,6 +47,9 @@ public class ResourceLoader {
|
||||
public ResourceLoader(@NonNull Engine engine) {
|
||||
long nativeEngine = engine.getNativeObject();
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, false, false, false);
|
||||
mNativeProvider = nCreateTextureProvider(nativeEngine);
|
||||
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeProvider);
|
||||
nAddTextureProvider(mNativeObject, "image/png", mNativeProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,6 +67,9 @@ public class ResourceLoader {
|
||||
long nativeEngine = engine.getNativeObject();
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, normalizeSkinningWeights,
|
||||
recomputeBoundingBoxes, ignoreBindTransform);
|
||||
mNativeProvider = nCreateTextureProvider(nativeEngine);
|
||||
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeProvider);
|
||||
nAddTextureProvider(mNativeObject, "image/png", mNativeProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,6 +77,7 @@ public class ResourceLoader {
|
||||
*/
|
||||
public void destroy() {
|
||||
nDestroyResourceLoader(mNativeObject);
|
||||
nDestroyTextureProvider(mNativeProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,4 +186,8 @@ public class ResourceLoader {
|
||||
private static native float nAsyncGetLoadProgress(long nativeLoader);
|
||||
private static native void nAsyncUpdateLoad(long nativeLoader);
|
||||
private static native void nAsyncCancelLoad(long nativeLoader);
|
||||
|
||||
private static native long nCreateTextureProvider(long nativeEngine);
|
||||
private static native void nAddTextureProvider(long nativeLoader, String url, long nativeProvider);
|
||||
private static native void nDestroyTextureProvider(long nativeProvider);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.21.0
|
||||
VERSION_NAME=1.21.3
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -150,12 +150,12 @@ class MainActivity : Activity() {
|
||||
val scene = modelViewer.scene
|
||||
val ibl = "default_env"
|
||||
readCompressedAsset("envs/$ibl/${ibl}_ibl.ktx").let {
|
||||
scene.indirectLight = KTXLoader.createIndirectLight(engine, it)
|
||||
scene.indirectLight = KTX1Loader.createIndirectLight(engine, it)
|
||||
scene.indirectLight!!.intensity = 30_000.0f
|
||||
viewerContent.indirectLight = modelViewer.scene.indirectLight
|
||||
}
|
||||
readCompressedAsset("envs/$ibl/${ibl}_skybox.ktx").let {
|
||||
scene.skybox = KTXLoader.createSkybox(engine, it)
|
||||
scene.skybox = KTX1Loader.createSkybox(engine, it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,9 +297,10 @@ class MainActivity : Activity() {
|
||||
|
||||
val gltfBuffer = pathToBufferMapping[gltfPath]!!
|
||||
|
||||
// The gltf is often not at the root level (e.g. if a folder is zipped) so
|
||||
// we need to extract its path in order to resolve the embedded uri strings.
|
||||
var prefix = URI(gltfPath!!).resolve("..")
|
||||
// In a zip file, the gltf file might be in the same folder as resources, or in a different
|
||||
// folder. It is crucial to test against both of these cases. In any case, the resource
|
||||
// paths are all specified relative to the location of the gltf file.
|
||||
var prefix = URI(gltfPath!!).resolve(".")
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if (gltfPath!!.endsWith(".glb")) {
|
||||
@@ -308,7 +309,7 @@ class MainActivity : Activity() {
|
||||
modelViewer.loadModelGltf(gltfBuffer) { uri ->
|
||||
val path = prefix.resolve(uri).toString()
|
||||
if (!pathToBufferMapping.contains(path)) {
|
||||
Log.e(TAG, "Could not find '$uri' in zip using prefix '$prefix'")
|
||||
Log.e(TAG, "Could not find '$uri' in zip using prefix '$prefix' and base path '${gltfPath!!}'")
|
||||
setStatusText("Zip is missing $path")
|
||||
}
|
||||
pathToBufferMapping[path]
|
||||
|
||||
@@ -79,8 +79,6 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
// Performs the rendering and schedules new frames
|
||||
private val frameScheduler = FrameCallback()
|
||||
|
||||
private var externalTextureID: Int = 0
|
||||
|
||||
@RequiresApi(30)
|
||||
class Api30Impl {
|
||||
companion object {
|
||||
@@ -103,8 +101,6 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
setupView()
|
||||
setupScene()
|
||||
|
||||
externalTextureID = createExternalTexture()
|
||||
|
||||
@Suppress("deprecation")
|
||||
val display = if (Build.VERSION.SDK_INT >= 30) {
|
||||
Api30Impl.getDisplay(this)
|
||||
@@ -112,7 +108,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
windowManager.defaultDisplay!!
|
||||
}
|
||||
|
||||
streamHelper = StreamHelper(engine, materialInstance, display, externalTextureID)
|
||||
streamHelper = StreamHelper(engine, materialInstance, display)
|
||||
this.title = streamHelper.getTestName()
|
||||
}
|
||||
|
||||
@@ -445,31 +441,4 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
check(EGL14.eglMakeCurrent(display, surface, surface, context)) { "Error making GL context." }
|
||||
return context
|
||||
}
|
||||
|
||||
private fun createExternalTexture(): Int {
|
||||
val textures = IntArray(1)
|
||||
GLES30.glGenTextures(1, textures, 0)
|
||||
val result = textures[0]
|
||||
|
||||
val textureTarget = GLES11Ext.GL_TEXTURE_EXTERNAL_OES
|
||||
GLES30.glBindTexture(textureTarget, result)
|
||||
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
|
||||
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
|
||||
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
|
||||
GLES30.glTexParameteri(textureTarget, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST)
|
||||
|
||||
if (!GLES30.glIsTexture(result)) {
|
||||
throw RuntimeException("OpenGL error: $result is an invalid texture.")
|
||||
}
|
||||
|
||||
val error = GLES30.glGetError()
|
||||
if (error != GLES30.GL_NO_ERROR) {
|
||||
val errorString = GLU.gluErrorString(error)
|
||||
throw RuntimeException("OpenGL error: $errorString!")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ class StreamHelper(
|
||||
private val filamentEngine: Engine,
|
||||
private val filamentMaterial: MaterialInstance,
|
||||
private val display: Display,
|
||||
private val externalTextureId: Int
|
||||
) {
|
||||
/**
|
||||
* The StreamSource configures the source data for the texture.
|
||||
@@ -51,7 +50,6 @@ class StreamHelper(
|
||||
*/
|
||||
enum class StreamSource {
|
||||
CANVAS_STREAM_NATIVE, // copy-free but does not guarantee synchronization
|
||||
CANVAS_STREAM_TEXID, // synchronized but incurs a copy
|
||||
CANVAS_STREAM_ACQUIRED, // synchronized and copy-free
|
||||
}
|
||||
|
||||
@@ -127,10 +125,6 @@ class StreamHelper(
|
||||
|
||||
surface.unlockCanvasAndPost(canvas)
|
||||
|
||||
if (streamSource == StreamSource.CANVAS_STREAM_TEXID) {
|
||||
surfaceTexture!!.updateTexImage()
|
||||
}
|
||||
|
||||
if (streamSource == StreamSource.CANVAS_STREAM_ACQUIRED) {
|
||||
val image = imageReader!!.acquireLatestImage()
|
||||
filamentStream!!.setAcquiredImage(
|
||||
@@ -146,7 +140,7 @@ class StreamHelper(
|
||||
|
||||
fun nextTest() {
|
||||
stopTest()
|
||||
streamSource = StreamSource.values()[(streamSource.ordinal + 1) % 3]
|
||||
streamSource = StreamSource.values()[(streamSource.ordinal + 1) % StreamSource.values().size]
|
||||
startTest()
|
||||
}
|
||||
|
||||
@@ -213,23 +207,6 @@ class StreamHelper(
|
||||
filamentTexture.setExternalStream(filamentEngine, filamentStream!!)
|
||||
}
|
||||
|
||||
if (streamSource == StreamSource.CANVAS_STREAM_TEXID) {
|
||||
|
||||
// Create the Android surface that will hold the canvas image.
|
||||
surfaceTexture = SurfaceTexture(externalTextureId)
|
||||
surfaceTexture!!.setDefaultBufferSize(resolution.width, resolution.height)
|
||||
canvasSurface = Surface(surfaceTexture)
|
||||
|
||||
// Create the Filament Stream object that gets bound to the Texture.
|
||||
filamentStream = Stream.Builder()
|
||||
.stream(externalTextureId.toLong())
|
||||
.width(resolution.width)
|
||||
.height(resolution.height)
|
||||
.build(filamentEngine)
|
||||
|
||||
filamentTexture.setExternalStream(filamentEngine, filamentStream!!)
|
||||
}
|
||||
|
||||
if (streamSource == StreamSource.CANVAS_STREAM_ACQUIRED) {
|
||||
filamentStream = Stream.Builder()
|
||||
.width(resolution.width)
|
||||
|
||||
BIN
art/diagrams/ImageUploadReadPixels.png
Normal file
BIN
art/diagrams/ImageUploadReadPixels.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
BIN
art/diagrams/NDC.png
Normal file
BIN
art/diagrams/NDC.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
art/diagrams/RenderingReadPixels.png
Normal file
BIN
art/diagrams/RenderingReadPixels.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
16
build.sh
16
build.sh
@@ -98,9 +98,9 @@ function print_matdbg_help {
|
||||
echo ""
|
||||
echo "FOR ANDROID BUILDS:"
|
||||
echo ""
|
||||
echo "1) The most reliable way to enable matdbg is to bypass Gradle and"
|
||||
echo " directly modify the appropriate two lines in the following file:"
|
||||
echo " ./android/filament-android/CMakeLists.txt"
|
||||
echo "1) For Android Studio builds, make sure to set:"
|
||||
echo " -Pcom.google.android.filament.matdbg"
|
||||
echo " option in Preferences > Build > Compiler > Command line options."
|
||||
echo ""
|
||||
echo "2) The port number is hardcoded to 8081 so you will need to do:"
|
||||
echo " adb forward tcp:8081 tcp:8081"
|
||||
@@ -156,6 +156,7 @@ VULKAN_ANDROID_GRADLE_OPTION=""
|
||||
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=OFF"
|
||||
|
||||
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
|
||||
MATDBG_GRADLE_OPTION=""
|
||||
|
||||
IOS_BUILD_SIMULATOR=false
|
||||
BUILD_UNIVERSAL_LIBRARIES=false
|
||||
@@ -303,7 +304,7 @@ function build_webgl_with_target {
|
||||
}
|
||||
|
||||
function build_webgl {
|
||||
# For the host tools, supress install and always use Release.
|
||||
# For the host tools, suppress install and always use Release.
|
||||
local old_install_command=${INSTALL_COMMAND}; INSTALL_COMMAND=
|
||||
local old_issue_debug_build=${ISSUE_DEBUG_BUILD}; ISSUE_DEBUG_BUILD=false
|
||||
local old_issue_release_build=${ISSUE_RELEASE_BUILD}; ISSUE_RELEASE_BUILD=true
|
||||
@@ -402,7 +403,7 @@ function ensure_android_build {
|
||||
function build_android {
|
||||
ensure_android_build
|
||||
|
||||
# Supress intermediate desktop tools install
|
||||
# Suppress intermediate desktop tools install
|
||||
local old_install_command=${INSTALL_COMMAND}
|
||||
INSTALL_COMMAND=
|
||||
|
||||
@@ -456,6 +457,7 @@ function build_android {
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${VULKAN_ANDROID_GRADLE_OPTION} \
|
||||
${MATDBG_GRADLE_OPTION} \
|
||||
:filament-android:assembleDebug \
|
||||
:gltfio-android:assembleDebug \
|
||||
:filament-utils-android:assembleDebug
|
||||
@@ -504,6 +506,7 @@ function build_android {
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${VULKAN_ANDROID_GRADLE_OPTION} \
|
||||
${MATDBG_GRADLE_OPTION} \
|
||||
:filament-android:assembleRelease \
|
||||
:gltfio-android:assembleRelease \
|
||||
:filament-utils-android:assembleRelease
|
||||
@@ -598,7 +601,7 @@ function archive_ios {
|
||||
}
|
||||
|
||||
function build_ios {
|
||||
# Supress intermediate desktop tools install
|
||||
# Suppress intermediate desktop tools install
|
||||
local old_install_command=${INSTALL_COMMAND}
|
||||
INSTALL_COMMAND=
|
||||
|
||||
@@ -754,6 +757,7 @@ while getopts ":hacCfijmp:q:uvslwtdk:" opt; do
|
||||
d)
|
||||
PRINT_MATDBG_HELP=true
|
||||
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_DISABLE_MATOPT=ON, -DFILAMENT_BUILD_FILAMAT=ON"
|
||||
MATDBG_GRADLE_OPTION="-Pcom.google.android.filament.matdbg"
|
||||
;;
|
||||
f)
|
||||
ISSUE_CMAKE_ALWAYS=true
|
||||
|
||||
14
build/common/requirements.txt
Normal file
14
build/common/requirements.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
setuptools==40.6.2
|
||||
wheel==0.37.1
|
||||
certifi==2021.10.8
|
||||
cffi==1.15.0
|
||||
charset-normalizer==2.0.12
|
||||
Deprecated==1.2.13
|
||||
idna==3.3
|
||||
pycparser==2.21
|
||||
PyGithub==1.55
|
||||
PyJWT==2.3.0
|
||||
PyNaCl==1.5.0
|
||||
requests==2.27.1
|
||||
urllib3==1.26.9
|
||||
wrapt==1.14.0
|
||||
@@ -11,3 +11,4 @@ tools/cmgen/test_cmgen compare
|
||||
tools/glslminifier/test_glslminifier
|
||||
libs/filameshio/test_filameshio
|
||||
libs/camutils/test_camutils
|
||||
libs/ktxreader/test_ktxreader
|
||||
|
||||
@@ -12,6 +12,25 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# requirements.txt created via:
|
||||
#
|
||||
# pip3 install virtualenv
|
||||
# python3 -m venv env
|
||||
# pip3 install PyGithub
|
||||
# pip3 install wheel
|
||||
# --all includes wheel and setuputils, which is needed for GitHub Actions
|
||||
# pip3 freeze --all > requirements.txt
|
||||
# Manually move 'setuptools' and 'wheel' lines to the beginning of the file.
|
||||
# Manually remove the 'pip' line.
|
||||
#
|
||||
# Requirements are installed in GitHub Actions via:
|
||||
# xargs -L 1 sudo pip3 install < build/common/requirements.txt
|
||||
# xargs must be used because the ordering of the dependencies matters (namely, setuptools).
|
||||
# sudo must be used to uninstall non-matching versions of packages.
|
||||
# pip is removed to avoid conflicts with the pre-installed pip version on Actions.
|
||||
# This technique does not work with Windows, unfortunately.
|
||||
|
||||
from github import Github
|
||||
import os, sys
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<canvas></canvas>
|
||||
<script src="//unpkg.com/filament@1.15.0/filament.js"></script>
|
||||
<script src="filament.js"></script>
|
||||
<script src="//unpkg.com/gl-matrix@2.8.1"></script>
|
||||
<script src="//unpkg.com/gltumble"></script>
|
||||
<script src="tutorial_redball.js"></script>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<canvas></canvas>
|
||||
<script src="//unpkg.com/filament@1.15.0/filament.js"></script>
|
||||
<script src="filament.js"></script>
|
||||
<script src="//unpkg.com/gl-matrix@2.8.1"></script>
|
||||
<script src="//unpkg.com/gltumble"></script>
|
||||
<script src="tutorial_suzanne.js"></script>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<canvas></canvas>
|
||||
<script src="//unpkg.com/filament@1.15.0/filament.js"></script>
|
||||
<script src="filament.js"></script>
|
||||
<script src="//unpkg.com/gl-matrix@2.8.1"></script>
|
||||
<script src="//unpkg.com/gltumble"></script>
|
||||
<script src="tutorial_triangle.js"></script>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -64,7 +64,7 @@
|
||||
<td align="left">Array of 16-bit or 32-bit unsigned integers consumed by the GPU.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left"><a href="#KtxBundle">KtxBundle</a></td>
|
||||
<td align="left"><a href="#Ktx1Bundle">Ktx1Bundle</a></td>
|
||||
<td align="left">In-memory representation of a KTX file.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -583,6 +583,11 @@
|
||||
<li><em>overrides</em> Dictionary with one or more of the following properties: enabled, sampleCount, customResolve.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>engine.setScreenSpaceReflectionsOptions(overrides)</strong>
|
||||
<ul>
|
||||
<li><em>overrides</em> Dictionary with one or more of the following properties: thickness, bias, maxDistance, stride, enabled.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>engine.setShadowOptions(instance, overrides)</strong>
|
||||
<ul>
|
||||
<li><em>instance</em> Instance of a light component obtained from <code>getInstance</code>.</li>
|
||||
@@ -662,63 +667,63 @@ as quaternions.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='classdoc'>
|
||||
<h2>class <a id='KtxBundle' href='#KtxBundle'>KtxBundle</a></h2>
|
||||
<h2>class <a id='Ktx1Bundle' href='#Ktx1Bundle'>Ktx1Bundle</a></h2>
|
||||
<p>In-memory representation of a KTX file.</p>
|
||||
<ul>
|
||||
<li><strong>ktxBundle.getArrayLength()</strong>
|
||||
<li><strong>ktx1Bundle.getArrayLength()</strong>
|
||||
<ul>
|
||||
<li>Obtains length of the texture array.</li>
|
||||
<li><em>returns</em> The number of elements in the texture array</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.getCompressedPixelDataType()</strong>
|
||||
<li><strong>ktx1Bundle.getCompressedPixelDataType()</strong>
|
||||
<ul>
|
||||
<li><em>returns</em> <a href="#CompressedPixelDataType">CompressedPixelDataType</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.getInternalFormat(srgb)</strong>
|
||||
<li><strong>ktx1Bundle.getInternalFormat(srgb)</strong>
|
||||
<ul>
|
||||
<li><em>srgb</em> boolean that forces the resulting format to SRGB if possible.</li>
|
||||
<li><em>returns</em> <a href="#Texture%24InternalFormat">Texture$InternalFormat</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.getMetadata(key)</strong>
|
||||
<li><strong>ktx1Bundle.getMetadata(key)</strong>
|
||||
<ul>
|
||||
<li>Obtains arbitrary metadata from the KTX file.</li>
|
||||
<li><em>key</em> string</li>
|
||||
<li><em>returns</em> string</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.getPixelDataFormat()</strong>
|
||||
<li><strong>ktx1Bundle.getPixelDataFormat()</strong>
|
||||
<ul>
|
||||
<li><em>returns</em> <a href="#PixelDataFormat">PixelDataFormat</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.getPixelDataType()</strong>
|
||||
<li><strong>ktx1Bundle.getPixelDataType()</strong>
|
||||
<ul>
|
||||
<li><em>returns</em> <a href="#PixelDataType">PixelDataType</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.info()</strong>
|
||||
<li><strong>ktx1Bundle.info()</strong>
|
||||
<ul>
|
||||
<li>Obtains properties of the KTX header.</li>
|
||||
<li><em>returns</em> The <a href="#KtxInfo">KtxInfo</a> property accessor object.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.info()</strong>
|
||||
<li><strong>ktx1Bundle.info()</strong>
|
||||
<ul>
|
||||
<li>Obtains properties of the KTX header.</li>
|
||||
<li><em>returns</em> The <a href="#KtxInfo">KtxInfo</a> property accessor object.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>ktxBundle.isCompressed()</strong>
|
||||
<li><strong>ktx1Bundle.isCompressed()</strong>
|
||||
<ul>
|
||||
<li><em>returns</em> boolean</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Most clients should use one of the <code>create*FromKtx</code> utility methods in the JavaScript <a href="#Engine">Engine</a>
|
||||
wrapper rather than interacting with <code>KtxBundle</code> directly.</p>
|
||||
wrapper rather than interacting with <code>Ktx1Bundle</code> directly.</p>
|
||||
</div>
|
||||
<div class='classdoc'>
|
||||
<h2>class <a id='KtxInfo' href='#KtxInfo'>KtxInfo</a></h2>
|
||||
@@ -743,7 +748,7 @@ wrapper rather than interacting with <code>KtxBundle</code> directly.</p>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>For example, <code>ktxbundle.info().pixelWidth</code>. See the
|
||||
<p>For example, <code>Ktx1Bundle.info().pixelWidth</code>. See the
|
||||
<a href="https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/">KTX spec</a> for the list of
|
||||
properties.</p>
|
||||
</div>
|
||||
@@ -1267,7 +1272,9 @@ This defines the following functions:</p>
|
||||
<ul>
|
||||
<li>POINTS</li>
|
||||
<li>LINES</li>
|
||||
<li>LINE_STRIP</li>
|
||||
<li>TRIANGLES</li>
|
||||
<li>TRIANGLE_STRIP</li>
|
||||
<li>NONE</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -12,7 +12,9 @@ textures.</p>
|
||||
<a href="tutorial_triangle.html">previous tutorial</a>. Change the last script tag from <code>triangle.js</code> to <code>redball.js</code>.</p>
|
||||
<p>Next you'll need to get a couple command-line tools: <code>matc</code> and <code>cmgen</code>. You can find these in the
|
||||
appropriate <a href="//github.com/google/filament/releases">Filament release</a>. You should choose the
|
||||
archive that corresponds to your development machine rather than the one for web.</p>
|
||||
archive that corresponds to your development machine rather than the one for web, and the version
|
||||
that matches the <code>unpkg.com/filament@x.x.x</code> url in the script tag of <code>redball.html</code> (you may check
|
||||
out the last available release of <a href="https://www.npmjs.com/package/filament">filament on npm</a>).</p>
|
||||
<h2>Define plastic material</h2>
|
||||
<p>The <code>matc</code> tool consumes a text file containing a high-level description of a PBR material, and
|
||||
produces a binary material package that contains shader code and associated metadata. For more
|
||||
@@ -60,12 +62,12 @@ IBL KTX contains these coefficients in its metadata.</p>
|
||||
<h2>Create JavaScript</h2>
|
||||
<p>Next, create <code>redball.js</code> with the following content.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span> environ <span style="color: #666666">=</span> <span style="color: #BA2121">'pillars_2k'</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> sky_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> sky_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> filamat_url <span style="color: #666666">=</span> <span style="color: #BA2121">'plastic.filamat'</span>
|
||||
|
||||
Filament.init([ filamat_url, ibl_url, sky_url ], () => {
|
||||
<span style="color: #408080; font-style: italic">// Create some global aliases to enums for convenience.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Create some global aliases to enums for convenience.</span>
|
||||
<span style="color: #008000">window</span>.VertexAttribute <span style="color: #666666">=</span> Filament.VertexAttribute;
|
||||
<span style="color: #008000">window</span>.AttributeType <span style="color: #666666">=</span> Filament.VertexBuffer$AttributeType;
|
||||
<span style="color: #008000">window</span>.PrimitiveType <span style="color: #666666">=</span> Filament.RenderableManager$PrimitiveType;
|
||||
@@ -73,7 +75,7 @@ Filament.init([ filamat_url, ibl_url, sky_url ], () => {
|
||||
<span style="color: #008000">window</span>.Fov <span style="color: #666666">=</span> Filament.Camera$Fov;
|
||||
<span style="color: #008000">window</span>.LightType <span style="color: #666666">=</span> Filament.LightManager$Type;
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span>
|
||||
<span style="color: #008000; font-weight: bold">const</span> canvas <span style="color: #666666">=</span> <span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">'canvas'</span>)[<span style="color: #666666">0</span>];
|
||||
<span style="color: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> App(canvas);
|
||||
} );
|
||||
@@ -84,11 +86,11 @@ Filament.init([ filamat_url, ibl_url, sky_url ], () => {
|
||||
<span style="color: #008000; font-weight: bold">const</span> engine <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine <span style="color: #666666">=</span> Filament.Engine.create(canvas);
|
||||
<span style="color: #008000; font-weight: bold">const</span> scene <span style="color: #666666">=</span> engine.createScene();
|
||||
|
||||
<span style="color: #408080; font-style: italic">// TODO: create material</span>
|
||||
<span style="color: #408080; font-style: italic">// TODO: create sphere</span>
|
||||
<span style="color: #408080; font-style: italic">// TODO: create lights</span>
|
||||
<span style="color: #408080; font-style: italic">// TODO: create IBL</span>
|
||||
<span style="color: #408080; font-style: italic">// TODO: create skybox</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create material</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create sphere</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create lights</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create IBL</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create skybox</span>
|
||||
|
||||
<span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> engine.createSwapChain();
|
||||
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> engine.createRenderer();
|
||||
@@ -209,9 +211,9 @@ following (don't type this out, there's an easier way).</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span> format <span style="color: #666666">=</span> Filament.PixelDataFormat.RGB;
|
||||
<span style="color: #008000; font-weight: bold">const</span> datatype <span style="color: #666666">=</span> Filament.PixelDataType.UINT_10F_11F_11F_REV;
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Create a Texture object for the mipmapped cubemap.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Create a Texture object for the mipmapped cubemap.</span>
|
||||
<span style="color: #008000; font-weight: bold">const</span> ibl_package <span style="color: #666666">=</span> Filament.Buffer(Filament.assets[ibl_url]);
|
||||
<span style="color: #008000; font-weight: bold">const</span> iblktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.KtxBundle(ibl_package);
|
||||
<span style="color: #008000; font-weight: bold">const</span> iblktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.Ktx1Bundle(ibl_package);
|
||||
|
||||
<span style="color: #008000; font-weight: bold">const</span> ibltex <span style="color: #666666">=</span> Filament.Texture.Builder()
|
||||
.width(iblktx.info().pixelWidth)
|
||||
@@ -227,11 +229,11 @@ following (don't type this out, there's an easier way).</p>
|
||||
ibltex.setImageCube(engine, level, pixelbuffer);
|
||||
}
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Parse the spherical harmonics metadata.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Parse the spherical harmonics metadata.</span>
|
||||
<span style="color: #008000; font-weight: bold">const</span> shstring <span style="color: #666666">=</span> iblktx.getMetadata(<span style="color: #BA2121">'sh'</span>);
|
||||
<span style="color: #008000; font-weight: bold">const</span> shfloats <span style="color: #666666">=</span> shstring.split(<span style="color: #BB6688">/\s/</span>, <span style="color: #666666">9</span> <span style="color: #666666">*</span> <span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>);
|
||||
<span style="color: #008000; font-weight: bold">const</span> shfloats <span style="color: #666666">=</span> shstring.split(<span style="color: #A45A77">/\s/</span>, <span style="color: #666666">9</span> <span style="color: #666666">*</span> <span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>);
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Build the IBL object and insert it into the scene.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Build the IBL object and insert it into the scene.</span>
|
||||
<span style="color: #008000; font-weight: bold">const</span> indirectLight <span style="color: #666666">=</span> Filament.IndirectLight.Builder()
|
||||
.reflections(ibltex)
|
||||
.irradianceSh(<span style="color: #666666">3</span>, shfloats)
|
||||
@@ -253,7 +255,7 @@ scene.setIndirectLight(indirectLight);
|
||||
Without a skybox, the reflections on the ball are not representative of its surroundings.
|
||||
Here's one way to create a texture for the skybox:</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">const</span> sky_package <span style="color: #666666">=</span> Filament.Buffer(Filament.assets[sky_url]);
|
||||
<span style="color: #008000; font-weight: bold">const</span> skyktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.KtxBundle(sky_package);
|
||||
<span style="color: #008000; font-weight: bold">const</span> skyktx <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> Filament.Ktx1Bundle(sky_package);
|
||||
<span style="color: #008000; font-weight: bold">const</span> skytex <span style="color: #666666">=</span> Filament.Texture.Builder()
|
||||
.width(skyktx.info().pixelWidth)
|
||||
.height(skyktx.info().pixelHeight)
|
||||
|
||||
@@ -22,25 +22,25 @@ converting <a href="https://github.com/google/filament/blob/main/assets/models/m
|
||||
<p>Next, let's create mipmapped KTX files using filament's <code>mipgen</code> tool. We'll create compressed and
|
||||
non-compressed variants for each texture, since not all platforms support the same compression
|
||||
formats. First copy over the PNG files from the <a href="https://github.com/google/filament/blob/main/assets/models/monkey">monkey folder</a>, then do:</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; font-style: italic"># Create mipmaps for base color and two compressed variants.</span>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic"># Create mipmaps for base color and two compressed variants.</span>
|
||||
mipgen albedo.png albedo.ktx
|
||||
mipgen --compression<span style="color: #666666">=</span>astc_fast_ldr_4x4 albedo.png albedo_astc.ktx
|
||||
mipgen --compression<span style="color: #666666">=</span>s3tc_rgb_dxt1 albedo.png albedo_s3tc_srgb.ktx
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Create mipmaps for the normal map and a compressed variant.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the normal map and a compressed variant.</span>
|
||||
mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear normal.png normal.ktx
|
||||
mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear --compression<span style="color: #666666">=</span>etc_rgb8_normalxyz_40 <span style="color: #BB6622; font-weight: bold">\</span>
|
||||
mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear --compression<span style="color: #666666">=</span>etc_rgb8_normalxyz_40 <span style="color: #AA5D1F; font-weight: bold">\</span>
|
||||
normal.png normal_etc.ktx
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Create mipmaps for the single-component roughness map and a compressed variant.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component roughness map and a compressed variant.</span>
|
||||
mipgen --grayscale roughness.png roughness.ktx
|
||||
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 roughness.png roughness_etc.ktx
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Create mipmaps for the single-component metallic map and a compressed variant.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component metallic map and a compressed variant.</span>
|
||||
mipgen --grayscale metallic.png metallic.ktx
|
||||
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 metallic.png metallic_etc.ktx
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Create mipmaps for the single-component occlusion map and a compressed variant.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic"># Create mipmaps for the single-component occlusion map and a compressed variant.</span>
|
||||
mipgen --grayscale ao.png ao.ktx
|
||||
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 ao.png ao_etc.ktx
|
||||
</pre></div>
|
||||
@@ -101,7 +101,7 @@ materials, consult the official document describing the <a href="https://google.
|
||||
<p>Create a text file called <code>suzanne.html</code> and copy over the HTML that we used in the <a href="tutorial_redball.html">previous
|
||||
tutorial</a>. Change the last script tag from <code>redball.js</code> to <code>suzanne.js</code>. Next, create <code>suzanne.js</code>
|
||||
with the following content.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; font-style: italic">// TODO: declare asset URLs</span>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic">// TODO: declare asset URLs</span>
|
||||
|
||||
Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () => {
|
||||
<span style="color: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #AA22FF; font-weight: bold">new</span> App(<span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">'canvas'</span>)[<span style="color: #666666">0</span>]);
|
||||
@@ -119,9 +119,9 @@ Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () => {
|
||||
<span style="color: #008000; font-weight: bold">const</span> filamesh <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.loadFilamesh(filamesh_url, <span style="color: #008000; font-weight: bold">this</span>.matinstance);
|
||||
<span style="color: #008000; font-weight: bold">this</span>.suzanne <span style="color: #666666">=</span> filamesh.renderable;
|
||||
|
||||
<span style="color: #408080; font-style: italic">// TODO: create sky box and IBL</span>
|
||||
<span style="color: #408080; font-style: italic">// TODO: initialize gltumble</span>
|
||||
<span style="color: #408080; font-style: italic">// TODO: fetch larger assets</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create sky box and IBL</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: initialize gltumble</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: fetch larger assets</span>
|
||||
|
||||
<span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSwapChain();
|
||||
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createRenderer();
|
||||
@@ -141,7 +141,7 @@ Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () => {
|
||||
}
|
||||
|
||||
render() {
|
||||
<span style="color: #408080; font-style: italic">// TODO: apply gltumble matrix</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: apply gltumble matrix</span>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain, <span style="color: #008000; font-weight: bold">this</span>.view);
|
||||
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
|
||||
}
|
||||
@@ -176,14 +176,14 @@ last resort. Go ahead and replace the <strong>declare asset URLs</strong> commen
|
||||
<span style="color: #008000; font-weight: bold">const</span> texture_suffix <span style="color: #666666">=</span> Filament.getSupportedFormatSuffix(<span style="color: #BA2121">'etc'</span>);
|
||||
|
||||
<span style="color: #008000; font-weight: bold">const</span> environ <span style="color: #666666">=</span> <span style="color: #BA2121">'venetian_crossroads_2k'</span>
|
||||
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> sky_small_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox_tiny.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> sky_large_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> albedo_url <span style="color: #666666">=</span> <span style="color: #BA2121">`albedo</span><span style="color: #BB6688; font-weight: bold">${</span>albedo_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> ao_url <span style="color: #666666">=</span> <span style="color: #BA2121">`ao</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> metallic_url <span style="color: #666666">=</span> <span style="color: #BA2121">`metallic</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> normal_url <span style="color: #666666">=</span> <span style="color: #BA2121">`normal</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> roughness_url <span style="color: #666666">=</span> <span style="color: #BA2121">`roughness</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> sky_small_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox_tiny.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> sky_large_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #A45A77; font-weight: bold">${</span>environ<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> albedo_url <span style="color: #666666">=</span> <span style="color: #BA2121">`albedo</span><span style="color: #A45A77; font-weight: bold">${</span>albedo_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> ao_url <span style="color: #666666">=</span> <span style="color: #BA2121">`ao</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> metallic_url <span style="color: #666666">=</span> <span style="color: #BA2121">`metallic</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> normal_url <span style="color: #666666">=</span> <span style="color: #BA2121">`normal</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> roughness_url <span style="color: #666666">=</span> <span style="color: #BA2121">`roughness</span><span style="color: #A45A77; font-weight: bold">${</span>texture_suffix<span style="color: #A45A77; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> filamat_url <span style="color: #666666">=</span> <span style="color: #BA2121">'textured.filamat'</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> filamesh_url <span style="color: #666666">=</span> <span style="color: #BA2121">'suzanne.filamesh'</span>;
|
||||
</pre></div>
|
||||
@@ -224,7 +224,7 @@ was created in the app constructor.</p>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'normal'</span>, normal, sampler);
|
||||
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'ao'</span>, ao, sampler);
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Replace low-res skybox with high-res skybox.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Replace low-res skybox with high-res skybox.</span>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.engine.destroySkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);
|
||||
<span style="color: #008000; font-weight: bold">this</span>.skybox <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx(sky_large_url);
|
||||
<span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);
|
||||
@@ -236,7 +236,7 @@ was created in the app constructor.</p>
|
||||
<h2>Introduce trackball rotation</h2>
|
||||
<p>Add the following script tag to your HTML file. This imports a small third-party library that
|
||||
listens for drag events and computes a rotation matrix.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"//unpkg.com/gltumble"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"//unpkg.com/gltumble"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
</pre></div>
|
||||
|
||||
<p>Next, replace the <strong>initialize gltumble</strong> and <strong>apply gltumble matrix</strong> comments with the following
|
||||
|
||||
@@ -16,22 +16,22 @@ subsequent code blocks.</p>
|
||||
<h2>Start your project</h2>
|
||||
<p>First, create a text file called <code>triangle.html</code> and fill it with the following HTML. This creates
|
||||
a mobile-friendly page with a full-screen canvas.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #BC7A00"><!DOCTYPE html></span>
|
||||
<<span style="color: #008000; font-weight: bold">html</span> <span style="color: #7D9029">lang</span><span style="color: #666666">=</span><span style="color: #BA2121">"en"</span>>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #9C6500"><!DOCTYPE html></span>
|
||||
<<span style="color: #008000; font-weight: bold">html</span> <span style="color: #687822">lang</span><span style="color: #666666">=</span><span style="color: #BA2121">"en"</span>>
|
||||
<<span style="color: #008000; font-weight: bold">head</span>>
|
||||
<<span style="color: #008000; font-weight: bold">title</span>>Filament Tutorial</<span style="color: #008000; font-weight: bold">title</span>>
|
||||
<<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #7D9029">charset</span><span style="color: #666666">=</span><span style="color: #BA2121">"utf-8"</span>>
|
||||
<<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #7D9029">name</span><span style="color: #666666">=</span><span style="color: #BA2121">"viewport"</span> <span style="color: #7D9029">content</span><span style="color: #666666">=</span><span style="color: #BA2121">"width=device-width,user-scalable=no,initial-scale=1"</span>>
|
||||
<<span style="color: #008000; font-weight: bold">style</span>>
|
||||
<span style="color: #008000; font-weight: bold">body</span> { <span style="color: #008000; font-weight: bold">margin</span>: <span style="color: #666666">0</span>; <span style="color: #008000; font-weight: bold">overflow</span>: <span style="color: #008000; font-weight: bold">hidden</span>; }
|
||||
<span style="color: #008000; font-weight: bold">canvas</span> { touch-action: <span style="color: #008000; font-weight: bold">none</span>; <span style="color: #008000; font-weight: bold">width</span>: <span style="color: #666666">100</span><span style="color: #B00040">%</span>; <span style="color: #008000; font-weight: bold">height</span>: <span style="color: #666666">100</span><span style="color: #B00040">%</span>; }
|
||||
</<span style="color: #008000; font-weight: bold">style</span>>
|
||||
<<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #687822">charset</span><span style="color: #666666">=</span><span style="color: #BA2121">"utf-8"</span>>
|
||||
<<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #687822">name</span><span style="color: #666666">=</span><span style="color: #BA2121">"viewport"</span> <span style="color: #687822">content</span><span style="color: #666666">=</span><span style="color: #BA2121">"width=device-width,user-scalable=no,initial-scale=1"</span>>
|
||||
<<span style="color: #008000; font-weight: bold">style</span>><span style="color: #bbbbbb"></span>
|
||||
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">body</span><span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">margin</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">overflow</span>:<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">hidden</span>;<span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
|
||||
<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">canvas</span><span style="color: #bbbbbb"> </span>{<span style="color: #bbbbbb"> </span>touch-action:<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">none</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">width</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">100</span><span style="color: #B00040">%</span>;<span style="color: #bbbbbb"> </span><span style="color: #008000; font-weight: bold">height</span>:<span style="color: #bbbbbb"> </span><span style="color: #666666">100</span><span style="color: #B00040">%</span>;<span style="color: #bbbbbb"> </span>}<span style="color: #bbbbbb"></span>
|
||||
<span style="color: #bbbbbb"> </span></<span style="color: #008000; font-weight: bold">style</span>>
|
||||
</<span style="color: #008000; font-weight: bold">head</span>>
|
||||
<<span style="color: #008000; font-weight: bold">body</span>>
|
||||
<<span style="color: #008000; font-weight: bold">canvas</span>></<span style="color: #008000; font-weight: bold">canvas</span>>
|
||||
<<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"//unpkg.com/filament@1.15.0/filament.js"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
<<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"//unpkg.com/gl-matrix@2.8.1"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
<<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"triangle.js"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
<<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"filament.js"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
<<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"//unpkg.com/gl-matrix@2.8.1"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
<<span style="color: #008000; font-weight: bold">script</span> <span style="color: #687822">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"triangle.js"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
||||
</<span style="color: #008000; font-weight: bold">body</span>>
|
||||
</<span style="color: #008000; font-weight: bold">html</span>>
|
||||
</pre></div>
|
||||
@@ -50,18 +50,18 @@ a mobile-friendly page with a full-screen canvas.</p>
|
||||
<p>Go ahead and create <code>triangle.js</code> with the following content.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">class</span> App {
|
||||
<span style="color: #008000; font-weight: bold">constructor</span>() {
|
||||
<span style="color: #408080; font-style: italic">// TODO: create entities</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: create entities</span>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.render <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>);
|
||||
<span style="color: #008000; font-weight: bold">this</span>.resize <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>);
|
||||
<span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">'resize'</span>, <span style="color: #008000; font-weight: bold">this</span>.resize);
|
||||
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
|
||||
}
|
||||
render() {
|
||||
<span style="color: #408080; font-style: italic">// TODO: render scene</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span>
|
||||
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
|
||||
}
|
||||
resize() {
|
||||
<span style="color: #408080; font-style: italic">// TODO: adjust viewport and canvas</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: adjust viewport and canvas</span>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +81,9 @@ that define a PBR material. We'll learn more about material packages in the next
|
||||
<h2>Spawn a local server</h2>
|
||||
<p>Because of CORS restrictions, your web app cannot fetch the material package directly from the
|
||||
file system. One way around this is to create a temporary server using Python or node:</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>python3 -m http.server <span style="color: #408080; font-style: italic"># Python 3</span>
|
||||
python -m SimpleHTTPServer <span style="color: #408080; font-style: italic"># Python 2.7</span>
|
||||
npx http-server -p <span style="color: #666666">8000</span> <span style="color: #408080; font-style: italic"># nodejs</span>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>python3 -m http.server <span style="color: #3D7B7B; font-style: italic"># Python 3</span>
|
||||
python -m SimpleHTTPServer <span style="color: #3D7B7B; font-style: italic"># Python 2.7</span>
|
||||
npx http-server -p <span style="color: #666666">8000</span> <span style="color: #3D7B7B; font-style: italic"># nodejs</span>
|
||||
</pre></div>
|
||||
|
||||
<p>To see if this works, navigate to <a href="http://localhost:8000">http://localhost:8000</a> and check if you
|
||||
@@ -185,10 +185,10 @@ view.</p>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera);
|
||||
<span style="color: #008000; font-weight: bold">this</span>.view.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene);
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Set up a blue-green background:</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Set up a blue-green background:</span>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.renderer.setClearOptions({clearColor<span style="color: #666666">:</span> [<span style="color: #666666">0.0</span>, <span style="color: #666666">0.1</span>, <span style="color: #666666">0.2</span>, <span style="color: #666666">1.0</span>], clear<span style="color: #666666">:</span> <span style="color: #008000; font-weight: bold">true</span>});
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Adjust the initial viewport:</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Adjust the initial viewport:</span>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.resize();
|
||||
</pre></div>
|
||||
|
||||
@@ -198,14 +198,14 @@ However the canvas is still blank!</p>
|
||||
<p>Recall that our App class has a skeletal render method, which the browser calls every time it needs
|
||||
to repaint. Often this is 60 times a second.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>render() {
|
||||
<span style="color: #408080; font-style: italic">// TODO: render scene</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// TODO: render scene</span>
|
||||
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
|
||||
}
|
||||
</pre></div>
|
||||
|
||||
<p>Let's flesh this out by rotating the triangle and invoking the Filament renderer. Add the following
|
||||
code to the top of the render method.</p>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; font-style: italic">// Rotate the triangle.</span>
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #3D7B7B; font-style: italic">// Rotate the triangle.</span>
|
||||
<span style="color: #008000; font-weight: bold">const</span> radians <span style="color: #666666">=</span> <span style="color: #008000">Date</span>.now() <span style="color: #666666">/</span> <span style="color: #666666">1000</span>;
|
||||
<span style="color: #008000; font-weight: bold">const</span> transform <span style="color: #666666">=</span> mat4.fromRotation(mat4.create(), radians, [<span style="color: #666666">0</span>, <span style="color: #666666">0</span>, <span style="color: #666666">1</span>]);
|
||||
<span style="color: #008000; font-weight: bold">const</span> tcm <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager();
|
||||
@@ -213,7 +213,7 @@ code to the top of the render method.</p>
|
||||
tcm.setTransform(inst, transform);
|
||||
inst.<span style="color: #AA22FF; font-weight: bold">delete</span>();
|
||||
|
||||
<span style="color: #408080; font-style: italic">// Render the frame.</span>
|
||||
<span style="color: #3D7B7B; font-style: italic">// Render the frame.</span>
|
||||
<span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain, <span style="color: #008000; font-weight: bold">this</span>.view);
|
||||
</pre></div>
|
||||
|
||||
|
||||
@@ -92,7 +92,6 @@ set(SRCS
|
||||
src/UniformBuffer.cpp
|
||||
src/VertexBuffer.cpp
|
||||
src/View.cpp
|
||||
src/Viewport.cpp
|
||||
src/components/CameraManager.cpp
|
||||
src/components/LightManager.cpp
|
||||
src/components/RenderableManager.cpp
|
||||
@@ -118,14 +117,14 @@ set(SRCS
|
||||
src/details/Texture.cpp
|
||||
src/details/VertexBuffer.cpp
|
||||
src/details/View.cpp
|
||||
src/fg2/Blackboard.cpp
|
||||
src/fg2/DependencyGraph.cpp
|
||||
src/fg2/FrameGraph.cpp
|
||||
src/fg2/FrameGraphPass.cpp
|
||||
src/fg2/FrameGraphResources.cpp
|
||||
src/fg2/FrameGraphTexture.cpp
|
||||
src/fg2/PassNode.cpp
|
||||
src/fg2/ResourceNode.cpp
|
||||
src/fg/Blackboard.cpp
|
||||
src/fg/DependencyGraph.cpp
|
||||
src/fg/FrameGraph.cpp
|
||||
src/fg/FrameGraphPass.cpp
|
||||
src/fg/FrameGraphResources.cpp
|
||||
src/fg/FrameGraphTexture.cpp
|
||||
src/fg/PassNode.cpp
|
||||
src/fg/ResourceNode.cpp
|
||||
src/fsr.cpp
|
||||
)
|
||||
|
||||
@@ -177,19 +176,19 @@ set(PRIVATE_HDRS
|
||||
src/details/Texture.h
|
||||
src/details/VertexBuffer.h
|
||||
src/details/View.h
|
||||
src/fg2/Blackboard.h
|
||||
src/fg2/FrameGraph.h
|
||||
src/fg2/FrameGraphId.h
|
||||
src/fg2/FrameGraphPass.h
|
||||
src/fg2/FrameGraphRenderPass.h
|
||||
src/fg2/FrameGraphResources.h
|
||||
src/fg2/FrameGraphTexture.h
|
||||
src/fg2/Resource.cpp
|
||||
src/fg2/details/DependencyGraph.h
|
||||
src/fg2/details/PassNode.h
|
||||
src/fg2/details/Resource.h
|
||||
src/fg2/details/ResourceNode.h
|
||||
src/fg2/details/Utilities.h
|
||||
src/fg/Blackboard.h
|
||||
src/fg/FrameGraph.h
|
||||
src/fg/FrameGraphId.h
|
||||
src/fg/FrameGraphPass.h
|
||||
src/fg/FrameGraphRenderPass.h
|
||||
src/fg/FrameGraphResources.h
|
||||
src/fg/FrameGraphTexture.h
|
||||
src/fg/Resource.cpp
|
||||
src/fg/details/DependencyGraph.h
|
||||
src/fg/details/PassNode.h
|
||||
src/fg/details/Resource.h
|
||||
src/fg/details/ResourceNode.h
|
||||
src/fg/details/Utilities.h
|
||||
src/fsr.h
|
||||
src/materials/fsr/ffx_a.h
|
||||
src/materials/fsr/ffx_fsr1.h
|
||||
|
||||
@@ -42,6 +42,7 @@ set(PRIVATE_HDRS
|
||||
include/private/backend/CircularBuffer.h
|
||||
include/private/backend/CommandBufferQueue.h
|
||||
include/private/backend/CommandStream.h
|
||||
include/private/backend/Dispatcher.h
|
||||
include/private/backend/Driver.h
|
||||
include/private/backend/DriverApi.h
|
||||
include/private/backend/DriverAPI.inc
|
||||
@@ -64,8 +65,6 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
|
||||
src/opengl/gl_headers.h
|
||||
src/opengl/GLUtils.cpp
|
||||
src/opengl/GLUtils.h
|
||||
src/opengl/OpenGLBlitter.cpp
|
||||
src/opengl/OpenGLBlitter.h
|
||||
src/opengl/OpenGLContext.cpp
|
||||
src/opengl/OpenGLContext.h
|
||||
src/opengl/OpenGLDriver.cpp
|
||||
@@ -74,8 +73,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
|
||||
src/opengl/OpenGLProgram.cpp
|
||||
src/opengl/OpenGLProgram.h
|
||||
src/opengl/OpenGLPlatform.cpp
|
||||
src/opengl/TimerQuery.cpp
|
||||
src/opengl/TimerQuery.h
|
||||
src/opengl/OpenGLTimerQuery.cpp
|
||||
src/opengl/OpenGLTimerQuery.h
|
||||
include/private/backend/OpenGLPlatform.h
|
||||
)
|
||||
if (EGL)
|
||||
@@ -88,7 +87,6 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
|
||||
endif ()
|
||||
if (ANDROID)
|
||||
list(APPEND SRCS src/opengl/platforms/ExternalStreamManagerAndroid.cpp)
|
||||
list(APPEND SRCS src/android/ExternalTextureManagerAndroid.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformEGLAndroid.cpp)
|
||||
elseif (IOS)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformCocoaTouchGL.mm)
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
/**
|
||||
* Types and enums used by filament's driver.
|
||||
*
|
||||
@@ -41,7 +40,7 @@ namespace filament {
|
||||
* internal redeclaration of these types.
|
||||
* For e.g. Use Texture::Sampler instead of filament::SamplerType.
|
||||
*/
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2;
|
||||
@@ -142,9 +141,9 @@ struct Viewport {
|
||||
uint32_t width; //!< width in pixels
|
||||
uint32_t height; //!< height in pixels
|
||||
//! get the right coordinate in window space of the viewport
|
||||
int32_t right() const noexcept { return left + width; }
|
||||
int32_t right() const noexcept { return left + int32_t(width); }
|
||||
//! get the top coordinate in window space of the viewport
|
||||
int32_t top() const noexcept { return bottom + height; }
|
||||
int32_t top() const noexcept { return bottom + int32_t(height); }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -160,7 +159,7 @@ struct DepthRange {
|
||||
* @see Fence, Fence::wait()
|
||||
*/
|
||||
enum class FenceStatus : int8_t {
|
||||
ERROR = -1, //!< An error occured. The Fence condition is not satisfied.
|
||||
ERROR = -1, //!< An error occurred. The Fence condition is not satisfied.
|
||||
CONDITION_SATISFIED = 0, //!< The Fence condition is satisfied.
|
||||
TIMEOUT_EXPIRED = 1, //!< wait()'s timeout expired. The Fence condition is not satisfied.
|
||||
};
|
||||
@@ -169,7 +168,7 @@ enum class FenceStatus : int8_t {
|
||||
* Status codes for sync objects
|
||||
*/
|
||||
enum class SyncStatus : int8_t {
|
||||
ERROR = -1, //!< An error occured. The Sync is not signaled.
|
||||
ERROR = -1, //!< An error occurred. The Sync is not signaled.
|
||||
SIGNALED = 0, //!< The Sync is signaled.
|
||||
NOT_SIGNALED = 1, //!< The Sync is not signaled yet
|
||||
};
|
||||
@@ -789,7 +788,6 @@ enum class BlendFunction : uint8_t {
|
||||
//! Stream for external textures
|
||||
enum class StreamType {
|
||||
NATIVE, //!< Not synchronized but copy-free. Good for video.
|
||||
TEXTURE_ID, //!< Synchronized, but GL-only and incurs copies. Good for AR on devices before API 26.
|
||||
ACQUIRED, //!< Synchronized, copy-free, and take a release callback. Good for AR but requires API 26+.
|
||||
};
|
||||
|
||||
@@ -998,8 +996,7 @@ enum class Workaround : uint16_t {
|
||||
ALLOW_READ_ONLY_ANCILLARY_FEEDBACK_LOOP
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::TargetBufferFlags>
|
||||
: public std::true_type {};
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
* underlying platform is returned and \p backendHint is updated
|
||||
* accordingly. Can't be nullptr.
|
||||
*
|
||||
* @return A pointer to the Plaform object.
|
||||
* @return A pointer to the Platform object.
|
||||
*
|
||||
* @see destroy
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#include <utility>
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
@@ -20,23 +18,19 @@
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_COMMANDSTREAM_H
|
||||
|
||||
#include "private/backend/CircularBuffer.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "private/backend/Program.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
#include "private/backend/Driver.h"
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
#include <backend/PresentCallable.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include "private/backend/Program.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
// FIXME: we'd like to not need this header here.
|
||||
#include "private/backend/Driver.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/ThreadUtils.h>
|
||||
|
||||
@@ -45,40 +39,14 @@
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Set to true to print every commands out on log.d. This requires RTTI and DEBUG
|
||||
// Set to true to print every command out on log.d. This requires RTTI and DEBUG
|
||||
#define DEBUG_COMMAND_STREAM false
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
class Driver;
|
||||
class CommandBase;
|
||||
|
||||
/*
|
||||
* Dispatcher is a data structure containing only function pointers.
|
||||
* Each function pointer targets code that unpacks the arguments to the driver's method and
|
||||
* calls it.
|
||||
*
|
||||
* Dispatcher's function pointers are populated during initialization and no CommandStream calls
|
||||
* can be made before that.
|
||||
*
|
||||
* When a command is inserted into the stream, the corresponding function pointer is copied
|
||||
* directly into CommandBase from Dispatcher.
|
||||
*/
|
||||
class Dispatcher {
|
||||
public:
|
||||
using Execute = void (*)(Driver& driver, CommandBase* self, intptr_t* next);
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) Execute methodName##_;
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) Execute methodName##_;
|
||||
#include "DriverAPI.inc"
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace filament::backend {
|
||||
|
||||
class CommandBase {
|
||||
static constexpr size_t FILAMENT_OBJECT_ALIGNMENT = alignof(std::max_align_t);
|
||||
@@ -96,8 +64,10 @@ public:
|
||||
|
||||
// executes this command and returns the next one
|
||||
inline CommandBase* execute(Driver& driver) {
|
||||
// it is important to return the next command offset by output parameter instead
|
||||
// of return value -- it allows the compiler to perform the tail call optimization.
|
||||
// returning the next command by output parameter allows the compiler to perform the
|
||||
// tail-call optimization in the function called by mExecute, however that comes at
|
||||
// a cost here (writing and reading the stack at each iteration), in the end it's
|
||||
// probably better to pay the cost at just one location.
|
||||
intptr_t next;
|
||||
mExecute(driver, this, &next);
|
||||
return reinterpret_cast<CommandBase*>(reinterpret_cast<intptr_t>(this) + next);
|
||||
@@ -132,7 +102,7 @@ constexpr decltype(auto) apply(M&& m, D&& d, T&& t) {
|
||||
/*
|
||||
* CommandType<> is just a wrapper class to specialize on a pointer-to-member of Driver
|
||||
* (i.e. a method pointer to a method of Driver of a particular type -- but not the
|
||||
* method itself). We only do that so we can identify the parameters of that method.
|
||||
* method itself). We only do that, so we can identify the parameters of that method.
|
||||
* We won't call through that pointer though.
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
@@ -208,7 +178,7 @@ class NoopCommand : public CommandBase {
|
||||
}
|
||||
public:
|
||||
inline constexpr explicit NoopCommand(void* next) noexcept
|
||||
: CommandBase(execute), mNext(size_t((char *)next - (char *)this)) { }
|
||||
: CommandBase(execute), mNext(intptr_t((char *)next - (char *)this)) { }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -216,41 +186,34 @@ public:
|
||||
#if !defined(NDEBUG) || (FILAMENT_DEBUG_COMMANDS >= FILAMENT_DEBUG_COMMANDS_ENABLE)
|
||||
// For now, simply pass the method name down as a string and throw away the parameters.
|
||||
// This is good enough for certain debugging needs and we can improve this later.
|
||||
#define DEBUG_COMMAND_BEGIN(methodName, sync, ...) mDriver->debugCommandBegin(this, sync, #methodName)
|
||||
#define DEBUG_COMMAND_END(methodName, sync) mDriver->debugCommandEnd(this, sync, #methodName)
|
||||
#define DEBUG_COMMAND_BEGIN(methodName, sync, ...) mDriver.debugCommandBegin(this, sync, #methodName)
|
||||
#define DEBUG_COMMAND_END(methodName, sync) mDriver.debugCommandEnd(this, sync, #methodName)
|
||||
#else
|
||||
#define DEBUG_COMMAND_BEGIN(methodName, sync, ...)
|
||||
#define DEBUG_COMMAND_END(methodName, sync)
|
||||
#endif
|
||||
|
||||
class CommandStream {
|
||||
// Dispatcher could be a value (instead of pointer), which saves a load when writing commands
|
||||
// at the expense of a larger CommandStream object (about ~400 bytes)
|
||||
Dispatcher* mDispatcher = nullptr;
|
||||
Driver* mDriver = nullptr;
|
||||
CircularBuffer* UTILS_RESTRICT mCurrentBuffer = nullptr;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// just for debugging...
|
||||
std::thread::id mThreadId{};
|
||||
#endif
|
||||
|
||||
bool mUsePerformanceCounter = false;
|
||||
|
||||
template<typename T>
|
||||
struct AutoExecute {
|
||||
T closure;
|
||||
inline AutoExecute(T&& closure) : closure(std::forward<T>(closure)) {}
|
||||
inline explicit AutoExecute(T&& closure) : closure(std::forward<T>(closure)) {}
|
||||
inline ~AutoExecute() { closure(); }
|
||||
};
|
||||
|
||||
public:
|
||||
CommandStream(Driver& driver, CircularBuffer& buffer) noexcept;
|
||||
|
||||
CommandStream(CommandStream const& rhs) noexcept = delete;
|
||||
CommandStream& operator=(CommandStream const& rhs) noexcept = delete;
|
||||
|
||||
public:
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
inline void methodName(paramsDecl) { \
|
||||
DEBUG_COMMAND_BEGIN(methodName, false, params); \
|
||||
using Cmd = COMMAND_TYPE(methodName); \
|
||||
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
|
||||
new(p) Cmd(mDispatcher->methodName##_, APPLY(std::move, params)); \
|
||||
new(p) Cmd(mDispatcher.methodName##_, APPLY(std::move, params)); \
|
||||
DEBUG_COMMAND_END(methodName, false); \
|
||||
}
|
||||
|
||||
@@ -260,16 +223,16 @@ public:
|
||||
AutoExecute callOnExit([=](){ \
|
||||
DEBUG_COMMAND_END(methodName, true); \
|
||||
}); \
|
||||
return apply(&Driver::methodName, *mDriver, std::forward_as_tuple(params)); \
|
||||
return apply(&Driver::methodName, mDriver, std::forward_as_tuple(params)); \
|
||||
}
|
||||
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) \
|
||||
inline RetType methodName(paramsDecl) { \
|
||||
DEBUG_COMMAND_BEGIN(methodName, false, params); \
|
||||
RetType result = mDriver->methodName##S(); \
|
||||
RetType result = mDriver.methodName##S(); \
|
||||
using Cmd = COMMAND_TYPE(methodName##R); \
|
||||
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
|
||||
new(p) Cmd(mDispatcher->methodName##_, RetType(result), APPLY(std::move, params)); \
|
||||
new(p) Cmd(mDispatcher.methodName##_, RetType(result), APPLY(std::move, params)); \
|
||||
DEBUG_COMMAND_END(methodName, false); \
|
||||
return result; \
|
||||
}
|
||||
@@ -277,10 +240,7 @@ public:
|
||||
#include "DriverAPI.inc"
|
||||
|
||||
public:
|
||||
CommandStream() noexcept = default;
|
||||
CommandStream(Driver& driver, CircularBuffer& buffer) noexcept;
|
||||
|
||||
// This is for debugging only. Currently CircularBuffer can only be written from a
|
||||
// This is for debugging only. Currently, CircularBuffer can only be written from a
|
||||
// single thread. In debug builds we assert this condition.
|
||||
// Call this first in the render loop.
|
||||
inline void debugThreading() noexcept {
|
||||
@@ -315,8 +275,21 @@ public:
|
||||
private:
|
||||
inline void* allocateCommand(size_t size) {
|
||||
assert_invariant(utils::ThreadUtils::isThisThread(mThreadId));
|
||||
return mCurrentBuffer->allocate(size);
|
||||
return mCurrentBuffer.allocate(size);
|
||||
}
|
||||
|
||||
// We use a copy of Dispatcher (instead of a pointer) because this removes one dereference
|
||||
// when executing driver commands.
|
||||
Driver& UTILS_RESTRICT mDriver;
|
||||
CircularBuffer& UTILS_RESTRICT mCurrentBuffer;
|
||||
Dispatcher mDispatcher;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// just for debugging...
|
||||
std::thread::id mThreadId{};
|
||||
#endif
|
||||
|
||||
bool mUsePerformanceCounter = false;
|
||||
};
|
||||
|
||||
void* CommandStream::allocate(size_t size, size_t alignment) noexcept {
|
||||
@@ -341,7 +314,6 @@ PodType* CommandStream::allocatePod(size_t count, size_t alignment) noexcept {
|
||||
return static_cast<PodType*>(allocate(count * sizeof(PodType), alignment));
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_COMMANDSTREAM_H
|
||||
|
||||
50
filament/backend/include/private/backend/Dispatcher.h
Normal file
50
filament/backend/include/private/backend/Dispatcher.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DISPATCHER_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_DISPATCHER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Driver;
|
||||
class CommandBase;
|
||||
|
||||
/*
|
||||
* Dispatcher is a data structure containing only function pointers.
|
||||
* Each function pointer targets code that unpacks the arguments to the driver's method and
|
||||
* calls it.
|
||||
*
|
||||
* Dispatcher's function pointers are populated during initialization and no CommandStream calls
|
||||
* can be made before that.
|
||||
*
|
||||
* When a command is inserted into the stream, the corresponding function pointer is copied
|
||||
* directly into CommandBase from Dispatcher.
|
||||
*/
|
||||
class Dispatcher {
|
||||
public:
|
||||
using Execute = void (*)(Driver& driver, CommandBase* self, intptr_t* next);
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) Execute methodName##_;
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) Execute methodName##_;
|
||||
|
||||
#include "DriverAPI.inc"
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif //TNT_FILAMENT_BACKEND_PRIVATE_DISPATCHER_H
|
||||
@@ -17,23 +17,14 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/CallbackHandler.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
#include <backend/PresentCallable.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include "private/backend/DriverApiForward.h"
|
||||
#include "private/backend/Program.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -49,8 +40,13 @@
|
||||
|
||||
#define FILAMENT_DEBUG_COMMANDS FILAMENT_DEBUG_COMMANDS_NONE
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
class BufferDescriptor;
|
||||
class CallbackHandler;
|
||||
class PixelBufferDescriptor;
|
||||
class Program;
|
||||
class SamplerGroup;
|
||||
|
||||
template<typename T>
|
||||
class ConcreteDispatcher;
|
||||
@@ -59,27 +55,32 @@ class CommandStream;
|
||||
|
||||
class Driver {
|
||||
public:
|
||||
static size_t getElementTypeSize(ElementType type) noexcept;
|
||||
|
||||
virtual ~Driver() noexcept;
|
||||
|
||||
static size_t getElementTypeSize(ElementType type) noexcept;
|
||||
|
||||
// called from the main thread (NOT the render-thread) at various intervals, this
|
||||
// is where the driver can execute user callbacks.
|
||||
virtual void purge() noexcept = 0;
|
||||
|
||||
virtual ShaderModel getShaderModel() const noexcept = 0;
|
||||
|
||||
virtual Dispatcher& getDispatcher() noexcept = 0;
|
||||
// Returns the dispatcher. This is only called once during initialization of the CommandStream,
|
||||
// so it doesn't matter that it's virtual.
|
||||
virtual Dispatcher getDispatcher() const noexcept = 0;
|
||||
|
||||
// called from CommandStream::execute on the render-thread
|
||||
// the fn function will execute a batch of driver commands
|
||||
// this gives the driver a chance to wrap their execution in a meaningful manner
|
||||
// the default implementation simply calls fn
|
||||
virtual void execute(std::function<void(void)> fn) noexcept;
|
||||
virtual void execute(std::function<void(void)> const& fn) noexcept;
|
||||
|
||||
// This is called on debug build, or when enabled manually on the backend thread side.
|
||||
virtual void debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept = 0;
|
||||
virtual void debugCommandEnd(CommandStream* cmds, bool synchronous, const char* methodName) noexcept = 0;
|
||||
virtual void debugCommandBegin(CommandStream* cmds,
|
||||
bool synchronous, const char* methodName) noexcept = 0;
|
||||
|
||||
virtual void debugCommandEnd(CommandStream* cmds,
|
||||
bool synchronous, const char* methodName) noexcept = 0;
|
||||
|
||||
/*
|
||||
* Asynchronous calls here only to provide a type to CommandStream. They must be non-virtual
|
||||
@@ -101,7 +102,6 @@ public:
|
||||
#include "private/backend/DriverAPI.inc"
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
|
||||
|
||||
@@ -246,11 +246,6 @@ DECL_DRIVER_API_R_N(backend::SwapChainHandle, createSwapChainHeadless,
|
||||
uint32_t, height,
|
||||
uint64_t, flags)
|
||||
|
||||
DECL_DRIVER_API_R_N(backend::StreamHandle, createStreamFromTextureId,
|
||||
intptr_t, externalTextureId,
|
||||
uint32_t, width,
|
||||
uint32_t, height)
|
||||
|
||||
DECL_DRIVER_API_R_0(backend::TimerQueryHandle, createTimerQuery)
|
||||
|
||||
|
||||
@@ -461,14 +456,6 @@ DECL_DRIVER_API_N(readPixels,
|
||||
uint32_t, height,
|
||||
backend::PixelBufferDescriptor&&, data)
|
||||
|
||||
DECL_DRIVER_API_N(readStreamPixels,
|
||||
backend::StreamHandle, sh,
|
||||
uint32_t, x,
|
||||
uint32_t, y,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
backend::PixelBufferDescriptor&&, data)
|
||||
|
||||
/*
|
||||
* Rendering operations
|
||||
* --------------------
|
||||
|
||||
@@ -17,15 +17,12 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPIFORWARD_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPIFORWARD_H
|
||||
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
class CommandStream;
|
||||
|
||||
using DriverApi = CommandStream;
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPIFORWARD_H
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
*/
|
||||
template<typename D, typename ... ARGS>
|
||||
Handle<D> allocateAndConstruct(ARGS&& ... args) noexcept {
|
||||
Handle<D> h{ allocateHandle(sizeof(D)) };
|
||||
Handle<D> h{ allocateHandle<sizeof(D)>() };
|
||||
D* addr = handle_cast<D*>(h);
|
||||
new(addr) D(std::forward<ARGS>(args)...);
|
||||
#if HANDLE_TYPE_SAFETY
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
*/
|
||||
template<typename D>
|
||||
Handle<D> allocate() noexcept {
|
||||
Handle<D> h{ allocateHandle(sizeof(D)) };
|
||||
Handle<D> h{ allocateHandle<sizeof(D)>() };
|
||||
#if HANDLE_TYPE_SAFETY
|
||||
D* addr = handle_cast<D*>(h);
|
||||
mLock.lock();
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
p->~D();
|
||||
deallocateHandle(handle.getId(), sizeof(D));
|
||||
deallocateHandle<sizeof(D)>(handle.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,23 +249,49 @@ private:
|
||||
utils::LockingPolicy::SpinLock>;
|
||||
#endif
|
||||
|
||||
// this is inlined because we're always called with a constexpr size
|
||||
HandleBase::HandleId allocateHandle(size_t size) noexcept {
|
||||
void* p = mHandleArena.alloc(size);
|
||||
if (UTILS_LIKELY(p)) {
|
||||
return pointerToHandle(p);
|
||||
// allocateHandle()/deallocateHandle() selects the pool to use at compile-time based on the
|
||||
// allocation size this is always inlined, because all these do is to call
|
||||
// allocateHandleInPool()/deallocateHandleFromPool() with the right pool size.
|
||||
template<size_t SIZE>
|
||||
HandleBase::HandleId allocateHandle() noexcept {
|
||||
if constexpr (SIZE <= P0) { return allocateHandleInPool<P0>(); }
|
||||
if constexpr (SIZE <= P1) { return allocateHandleInPool<P1>(); }
|
||||
return allocateHandleInPool<P2>();
|
||||
}
|
||||
|
||||
template<size_t SIZE>
|
||||
void deallocateHandle(HandleBase::HandleId id) noexcept {
|
||||
if constexpr (SIZE <= P0) {
|
||||
deallocateHandleFromPool<P0>(id);
|
||||
} else if constexpr (SIZE <= P1) {
|
||||
deallocateHandleFromPool<P1>(id);
|
||||
} else {
|
||||
return allocateHandleSlow(size);
|
||||
deallocateHandleFromPool<P2>(id);
|
||||
}
|
||||
}
|
||||
|
||||
// this is inlined because we're always called with a constexpr size
|
||||
void deallocateHandle(HandleBase::HandleId id, size_t size) noexcept {
|
||||
// allocateHandleInPool()/deallocateHandleFromPool() is NOT inlined, which will cause three
|
||||
// versions to be generated, one for each pool. Because the arena is synchronized,
|
||||
// the code generated is not trivial (even if it's not insane either).
|
||||
template<size_t SIZE>
|
||||
UTILS_NOINLINE
|
||||
HandleBase::HandleId allocateHandleInPool() noexcept {
|
||||
void* p = mHandleArena.alloc(SIZE);
|
||||
if (UTILS_LIKELY(p)) {
|
||||
return pointerToHandle(p);
|
||||
} else {
|
||||
return allocateHandleSlow(SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t SIZE>
|
||||
UTILS_NOINLINE
|
||||
void deallocateHandleFromPool(HandleBase::HandleId id) noexcept {
|
||||
if (UTILS_LIKELY(isPoolHandle(id))) {
|
||||
void* p = handleToPointer(id);
|
||||
mHandleArena.free(p, size);
|
||||
mHandleArena.free(p, SIZE);
|
||||
} else {
|
||||
deallocateHandleSlow(id, size);
|
||||
deallocateHandleSlow(id, SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,15 +82,6 @@ public:
|
||||
virtual void detach(Stream* stream) noexcept = 0;
|
||||
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept = 0;
|
||||
|
||||
// external texture storage
|
||||
virtual ExternalTexture* createExternalTextureStorage() noexcept = 0;
|
||||
|
||||
// this is called synchronously in the application thread (NOT the Driver thread)
|
||||
virtual void reallocateExternalStorage(ExternalTexture* ets,
|
||||
uint32_t w, uint32_t h, TextureFormat format) noexcept = 0;
|
||||
|
||||
virtual void destroyExternalTextureStorage(ExternalTexture* ets) noexcept = 0;
|
||||
|
||||
// The method allows platforms to convert a user-supplied external image object into a new type
|
||||
// (e.g. HardwareBuffer => EGLImage). It makes sense for the default implementation to do nothing.
|
||||
virtual AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept { return source; }
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
CircularBuffer::CircularBuffer(size_t size) {
|
||||
mData = alloc(size);
|
||||
@@ -56,6 +55,7 @@ CircularBuffer::~CircularBuffer() noexcept {
|
||||
// If the system does not support mmap, emulate soft circular buffer with two buffers next
|
||||
// to each others and a special case in circularize()
|
||||
|
||||
UTILS_NOINLINE
|
||||
void* CircularBuffer::alloc(size_t size) noexcept {
|
||||
#if HAS_MMAP
|
||||
void* data = nullptr;
|
||||
@@ -127,6 +127,7 @@ void* CircularBuffer::alloc(size_t size) noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void CircularBuffer::dealloc() noexcept {
|
||||
#if HAS_MMAP
|
||||
if (mData) {
|
||||
@@ -162,5 +163,4 @@ void CircularBuffer::circularize() noexcept {
|
||||
mTail = mHead;
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// A few utility functions for debugging...
|
||||
@@ -57,9 +56,9 @@ static UTILS_NOINLINE UTILS_UNUSED std::string extractMethodName(std::string& co
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
CommandStream::CommandStream(Driver& driver, CircularBuffer& buffer) noexcept
|
||||
: mDispatcher(&driver.getDispatcher()),
|
||||
mDriver(&driver),
|
||||
mCurrentBuffer(&buffer)
|
||||
: mDriver(driver),
|
||||
mCurrentBuffer(buffer),
|
||||
mDispatcher(driver.getDispatcher())
|
||||
#ifndef NDEBUG
|
||||
, mThreadId(ThreadUtils::getThreadId())
|
||||
#endif
|
||||
@@ -84,8 +83,8 @@ void CommandStream::execute(void* buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
mDriver->execute([this, buffer]() {
|
||||
Driver& UTILS_RESTRICT driver = *mDriver;
|
||||
mDriver.execute([this, buffer]() {
|
||||
Driver& UTILS_RESTRICT driver = mDriver;
|
||||
CommandBase* UTILS_RESTRICT base = static_cast<CommandBase*>(buffer);
|
||||
while (UTILS_LIKELY(base)) {
|
||||
base = base->execute(driver);
|
||||
@@ -152,5 +151,4 @@ void CustomCommand::execute(Driver&, CommandBase* base, intptr_t* next) noexcept
|
||||
static_cast<CustomCommand*>(base)->~CustomCommand();
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define DEBUG_LEVEL_NONE 0
|
||||
@@ -46,10 +46,10 @@
|
||||
namespace filament::backend {
|
||||
|
||||
template<typename ConcreteDriver>
|
||||
class ConcreteDispatcher final : public Dispatcher {
|
||||
class ConcreteDispatcher {
|
||||
public:
|
||||
// initialize the dispatch table
|
||||
ConcreteDispatcher() noexcept;
|
||||
|
||||
static Dispatcher make() noexcept;
|
||||
|
||||
private:
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
|
||||
@@ -72,13 +72,19 @@ private:
|
||||
|
||||
template<typename ConcreteDriver>
|
||||
UTILS_NOINLINE
|
||||
ConcreteDispatcher<ConcreteDriver>::ConcreteDispatcher() noexcept : Dispatcher() {
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) methodName##_ = &ConcreteDispatcher::methodName;
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) methodName##_ = &ConcreteDispatcher::methodName;
|
||||
#include "private/backend/DriverAPI.inc"
|
||||
}
|
||||
Dispatcher ConcreteDispatcher<ConcreteDriver>::make() noexcept {
|
||||
Dispatcher dispatcher;
|
||||
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params)
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
dispatcher.methodName##_ = &ConcreteDispatcher::methodName;
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) \
|
||||
dispatcher.methodName##_ = &ConcreteDispatcher::methodName;
|
||||
|
||||
#include "private/backend/DriverAPI.inc"
|
||||
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
|
||||
#include "private/backend/Driver.h"
|
||||
|
||||
#include "private/backend/AcquiredImage.h"
|
||||
#include "private/backend/CommandStream.h"
|
||||
|
||||
#include "DriverBase.h"
|
||||
@@ -25,20 +27,15 @@
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
using namespace utils;
|
||||
using namespace filament::math;
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
using namespace math;
|
||||
|
||||
namespace backend {
|
||||
|
||||
DriverBase::DriverBase(Dispatcher* dispatcher) noexcept
|
||||
: mDispatcher(dispatcher) {
|
||||
DriverBase::DriverBase() noexcept {
|
||||
if constexpr (UTILS_HAS_THREADING) {
|
||||
// This thread services user callbacks
|
||||
mServiceThread = std::thread([this]() {
|
||||
@@ -75,7 +72,6 @@ DriverBase::~DriverBase() noexcept {
|
||||
lock.unlock();
|
||||
mServiceThread.join();
|
||||
}
|
||||
delete mDispatcher;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -169,14 +165,6 @@ void DriverBase::debugCommandEnd(CommandStream* cmds, bool synchronous, const ch
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
Driver::~Driver() noexcept = default;
|
||||
|
||||
void Driver::execute(std::function<void(void)> fn) noexcept {
|
||||
fn();
|
||||
}
|
||||
|
||||
size_t Driver::getElementTypeSize(ElementType type) noexcept {
|
||||
switch (type) {
|
||||
case ElementType::BYTE: return sizeof(int8_t);
|
||||
@@ -208,5 +196,12 @@ size_t Driver::getElementTypeSize(ElementType type) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
Driver::~Driver() noexcept = default;
|
||||
|
||||
void Driver::execute(std::function<void(void)> const& fn) noexcept {
|
||||
fn();
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/CallbackHandler.h>
|
||||
|
||||
#include "private/backend/AcquiredImage.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "private/backend/Driver.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
#include <array>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Dispatcher;
|
||||
struct AcquiredImage;
|
||||
|
||||
/*
|
||||
* Hardware handles
|
||||
@@ -72,7 +72,7 @@ struct HwBufferObject : public HwBase {
|
||||
uint32_t byteCount{};
|
||||
|
||||
HwBufferObject() noexcept = default;
|
||||
HwBufferObject(uint32_t byteCount) noexcept : byteCount(byteCount) {}
|
||||
explicit HwBufferObject(uint32_t byteCount) noexcept : byteCount(byteCount) {}
|
||||
};
|
||||
|
||||
struct HwIndexBuffer : public HwBase {
|
||||
@@ -167,21 +167,16 @@ struct HwTimerQuery : public HwBase {
|
||||
|
||||
class DriverBase : public Driver {
|
||||
public:
|
||||
DriverBase() = delete;
|
||||
explicit DriverBase(Dispatcher* dispatcher) noexcept;
|
||||
DriverBase() noexcept;
|
||||
~DriverBase() noexcept override;
|
||||
|
||||
void purge() noexcept final;
|
||||
|
||||
Dispatcher& getDispatcher() noexcept final { return *mDispatcher; }
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Privates
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
Dispatcher* mDispatcher;
|
||||
|
||||
class CallbackDataDetails;
|
||||
|
||||
// Helpers...
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace filament::backend {
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
static char const * const kOurNamespace = "filament::";
|
||||
static char const * const kOurNamespace = "filament::backend";
|
||||
|
||||
// removes all occurrences of "what" from "str"
|
||||
UTILS_NOINLINE
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ExternalTextureManagerAndroid.h"
|
||||
|
||||
#include <utils/api_level.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
using namespace backend;
|
||||
|
||||
template <typename T>
|
||||
static void loadSymbol(T*& pfn, const char *symbol) noexcept {
|
||||
pfn = (T*)dlsym(RTLD_DEFAULT, symbol);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ndk {
|
||||
/*
|
||||
* This mimics the GraphicBuffer class for pre-API 26
|
||||
*/
|
||||
template<typename NATIVE_TYPE, typename REF>
|
||||
struct ANativeObjectBase : public NATIVE_TYPE, public REF {
|
||||
};
|
||||
|
||||
struct android_native_base_t {
|
||||
unsigned int magic;
|
||||
unsigned int version;
|
||||
void* reserved[4];
|
||||
void (* incRef)(struct android_native_base_t* base);
|
||||
void (* decRef)(struct android_native_base_t* base);
|
||||
};
|
||||
|
||||
struct ANativeWindowBuffer {
|
||||
struct android_native_base_t common;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int stride;
|
||||
unsigned int format;
|
||||
unsigned int usage_deprecated;
|
||||
uintptr_t layerCount;
|
||||
void* reserved[1];
|
||||
const void* handle;
|
||||
uint64_t usage;
|
||||
void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
|
||||
};
|
||||
|
||||
struct RefBase {
|
||||
virtual ~RefBase() = default;
|
||||
void* ref;
|
||||
};
|
||||
|
||||
struct GraphicBuffer : public ANativeObjectBase<ANativeWindowBuffer, RefBase> {
|
||||
};
|
||||
struct GraphicBufferWrapper {
|
||||
GraphicBuffer* graphicBuffer;
|
||||
};
|
||||
} // namespace ndk
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
using namespace ndk;
|
||||
|
||||
struct EGLExternalTexture : public ExternalTextureManagerAndroid::ExternalTexture {
|
||||
GraphicBufferWrapper* graphicBufferWrapper = nullptr;
|
||||
};
|
||||
|
||||
ExternalTextureManagerAndroid& ExternalTextureManagerAndroid::create() noexcept {
|
||||
return *(new ExternalTextureManagerAndroid{});
|
||||
}
|
||||
|
||||
void ExternalTextureManagerAndroid::destroy(ExternalTextureManagerAndroid* pExternalTextureManager) noexcept {
|
||||
delete pExternalTextureManager;
|
||||
}
|
||||
|
||||
// called on gl thread
|
||||
ExternalTextureManagerAndroid::ExternalTextureManagerAndroid() noexcept
|
||||
: mVm(VirtualMachineEnv::get()) {
|
||||
}
|
||||
|
||||
// not quite sure on which thread this is going to be called
|
||||
ExternalTextureManagerAndroid::~ExternalTextureManagerAndroid() noexcept {
|
||||
if (__builtin_available(android 26, *)) {
|
||||
} else {
|
||||
if (mGraphicBufferClass) {
|
||||
JNIEnv* env = VirtualMachineEnv::getThreadEnvironment();
|
||||
if (env) {
|
||||
env->DeleteGlobalRef(mGraphicBufferClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called on gl thread
|
||||
backend::Platform::ExternalTexture* ExternalTextureManagerAndroid::createExternalTexture() noexcept {
|
||||
if (__builtin_available(android 26, *)) {
|
||||
} else {
|
||||
// initialize java stuff on-demand
|
||||
if (!mGraphicBufferClass) {
|
||||
JNIEnv* env = mVm.getEnvironment();
|
||||
mGraphicBufferClass = env->FindClass("android/view/GraphicBuffer");
|
||||
mGraphicBuffer_nCreateGraphicBuffer = env->GetStaticMethodID(
|
||||
mGraphicBufferClass, "nCreateGraphicBuffer", "(IIII)J");
|
||||
mGraphicBuffer_nDestroyGraphicBuffer = env->GetStaticMethodID(
|
||||
mGraphicBufferClass, "nDestroyGraphicBuffer", "(J)V");
|
||||
|
||||
mGraphicBufferClass = static_cast<jclass>(env->NewGlobalRef(mGraphicBufferClass));
|
||||
}
|
||||
}
|
||||
EGLExternalTexture* ets = new EGLExternalTexture;
|
||||
return ets;
|
||||
}
|
||||
|
||||
// called on app thread
|
||||
void ExternalTextureManagerAndroid::reallocate(
|
||||
backend::Platform::ExternalTexture* ets, uint32_t w, uint32_t h,
|
||||
backend::TextureFormat format, uint64_t usage) noexcept {
|
||||
destroyStorage(ets);
|
||||
alloc(ets, w, h, format, usage);
|
||||
}
|
||||
|
||||
// called on gl thread
|
||||
void ExternalTextureManagerAndroid::destroy(backend::Platform::ExternalTexture* ets) noexcept {
|
||||
destroyStorage(ets);
|
||||
delete static_cast<EGLExternalTexture*>(ets);
|
||||
}
|
||||
|
||||
// called on app thread
|
||||
void ExternalTextureManagerAndroid::alloc(
|
||||
backend::Platform::ExternalTexture* t,
|
||||
uint32_t w, uint32_t h, TextureFormat format, uint64_t usage) noexcept {
|
||||
|
||||
EGLExternalTexture* ets = static_cast<EGLExternalTexture*>(t);
|
||||
|
||||
AHardwareBuffer_Desc desc = { w, h, 1, 0, usage, 0, 0, 0 };
|
||||
switch (format) {
|
||||
case TextureFormat::RGB8:
|
||||
// don't use R8G8B8 here because some drivers produce garbled images
|
||||
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
|
||||
break;
|
||||
case TextureFormat::RGBA8:
|
||||
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case TextureFormat::RGB565:
|
||||
desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
|
||||
break;
|
||||
case TextureFormat::RGB10_A2:
|
||||
desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
default:
|
||||
slog.e << "Unsupported format " << (int)format << ", use RGBA8 or RGB8 only."
|
||||
<< io::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (__builtin_available(android 26, *)) {
|
||||
// allocate new storage...
|
||||
AHardwareBuffer* buffer = nullptr;
|
||||
if (AHardwareBuffer_allocate(&desc, &buffer) < 0) {
|
||||
slog.e << "AHardwareBuffer_allocate() failed" << io::endl;
|
||||
return;
|
||||
}
|
||||
ets->hardwareBuffer = buffer;
|
||||
} else {
|
||||
// note: This is called on the application thread (not the GL thread)
|
||||
JNIEnv* env = VirtualMachineEnv::getThreadEnvironment();
|
||||
if (!env) {
|
||||
return; // this should not happen
|
||||
}
|
||||
|
||||
jlong graphicBufferWrapperJni = env->CallStaticLongMethod(mGraphicBufferClass,
|
||||
mGraphicBuffer_nCreateGraphicBuffer, w, h, desc.format, usage);
|
||||
VirtualMachineEnv::handleException(env);
|
||||
|
||||
if (graphicBufferWrapperJni) {
|
||||
GraphicBuffer* const gb = ((GraphicBufferWrapper*)graphicBufferWrapperJni)->graphicBuffer;
|
||||
ets->graphicBufferWrapper = (GraphicBufferWrapper*)graphicBufferWrapperJni;
|
||||
ets->clientBuffer = static_cast<ANativeWindowBuffer*>(gb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called on gl thread
|
||||
void ExternalTextureManagerAndroid::destroyStorage(backend::Platform::ExternalTexture* t) noexcept {
|
||||
EGLExternalTexture* ets = static_cast<EGLExternalTexture*>(t);
|
||||
if (__builtin_available(android 26, *)) {
|
||||
// destroy the current storage if any
|
||||
if (ets->hardwareBuffer) {
|
||||
AHardwareBuffer_release(ets->hardwareBuffer);
|
||||
ets->hardwareBuffer = nullptr;
|
||||
}
|
||||
} else {
|
||||
if (ets->graphicBufferWrapper) {
|
||||
JNIEnv* env = VirtualMachineEnv::get().getEnvironment();
|
||||
env->CallStaticVoidMethod(mGraphicBufferClass,
|
||||
mGraphicBuffer_nDestroyGraphicBuffer, (jlong)ets->graphicBufferWrapper);
|
||||
VirtualMachineEnv::handleException(env);
|
||||
ets->graphicBufferWrapper = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
|
||||
#define TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
|
||||
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <android/hardware_buffer.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
/*
|
||||
* ExternalTextureManagerAndroid::ExternalTexture is basically a wrapper for AHardwareBuffer.
|
||||
*
|
||||
* This class doesn't rely on GL or EGL, and could be used for other Android platform if needed
|
||||
* (e.g. Vulkan).
|
||||
*
|
||||
* ExternalTextureManagerAndroid handle allocation/destruction using either Java or the NDK,
|
||||
* whichever is available.
|
||||
*/
|
||||
class ExternalTextureManagerAndroid {
|
||||
public:
|
||||
|
||||
struct ExternalTexture : public backend::Platform::ExternalTexture {
|
||||
void* clientBuffer = nullptr;
|
||||
AHardwareBuffer* hardwareBuffer = nullptr;
|
||||
};
|
||||
|
||||
// must be called on backend thread
|
||||
static ExternalTextureManagerAndroid& create() noexcept;
|
||||
|
||||
// must be called on backend thread
|
||||
static void destroy(ExternalTextureManagerAndroid* pExternalTextureManager) noexcept;
|
||||
|
||||
// must be called on backend thread (only because we don't synchronize
|
||||
backend::Platform::ExternalTexture* createExternalTexture() noexcept;
|
||||
|
||||
// called on app thread
|
||||
void reallocate(
|
||||
backend::Platform::ExternalTexture* ets, uint32_t w, uint32_t h,
|
||||
backend::TextureFormat format, uint64_t usage) noexcept;
|
||||
|
||||
// must be called on backend thread
|
||||
void destroy(backend::Platform::ExternalTexture* ets) noexcept;
|
||||
|
||||
private:
|
||||
ExternalTextureManagerAndroid() noexcept;
|
||||
~ExternalTextureManagerAndroid() noexcept;
|
||||
|
||||
// called on app thread
|
||||
void alloc(backend::Platform::ExternalTexture* ets,
|
||||
uint32_t w, uint32_t h, backend::TextureFormat format, uint64_t usage) noexcept;
|
||||
|
||||
// called on gl thread
|
||||
void destroyStorage(backend::Platform::ExternalTexture* ets) noexcept;
|
||||
|
||||
VirtualMachineEnv& mVm;
|
||||
|
||||
jclass mGraphicBufferClass = nullptr;
|
||||
jmethodID mGraphicBuffer_nCreateGraphicBuffer = nullptr;
|
||||
jmethodID mGraphicBuffer_nDestroyGraphicBuffer = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
struct MetalContext;
|
||||
|
||||
@@ -133,7 +132,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
static const char* functionLibrary = R"(
|
||||
#include <metal_stdlib>
|
||||
@@ -300,7 +299,7 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
|
||||
}
|
||||
id<MTLFunction> fragmentFunction = getBlitFragmentFunction(key);
|
||||
|
||||
PipelineState pipelineState {
|
||||
MetalPipelineState pipelineState {
|
||||
.vertexFunction = getBlitVertexFunction(),
|
||||
.fragmentFunction = fragmentFunction,
|
||||
.vertexDescription = {},
|
||||
@@ -530,6 +529,5 @@ id<MTLFunction> MetalBlitter::getBlitFragmentFunction(BlitFunctionKey key) {
|
||||
return function;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
class MetalBuffer {
|
||||
public:
|
||||
@@ -94,7 +93,6 @@ private:
|
||||
void copyIntoStreamBuffer(void* src, size_t size);
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
MetalBuffer::MetalBuffer(MetalContext& context, BufferUsage usage, size_t size, bool forceGpuBuffer)
|
||||
: mBufferSize(size), mContext(context) {
|
||||
@@ -206,6 +205,5 @@ void MetalBuffer::bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLRenderComman
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
struct MetalContext;
|
||||
|
||||
@@ -78,7 +77,6 @@ private:
|
||||
static constexpr uint32_t TIME_BEFORE_EVICTION = 10;
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
MetalBufferPoolEntry const* MetalBufferPool::acquireBuffer(size_t numBytes) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
@@ -110,6 +109,5 @@ void MetalBufferPool::reset() noexcept {
|
||||
mFreeStages.clear();
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -36,14 +36,13 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
class MetalDriver;
|
||||
class MetalBlitter;
|
||||
class MetalBufferPool;
|
||||
class MetalRenderTarget;
|
||||
class MetalSwapChain;
|
||||
class TimerQueryInterface;
|
||||
class MetalTimerQueryInterface;
|
||||
struct MetalUniformBuffer;
|
||||
struct MetalIndexBuffer;
|
||||
struct MetalSamplerGroup;
|
||||
@@ -113,7 +112,7 @@ struct MetalContext {
|
||||
MTLSharedEventListener* eventListener = nil;
|
||||
uint64_t signalId = 1;
|
||||
|
||||
TimerQueryInterface* timerQueryImpl;
|
||||
MetalTimerQueryInterface* timerQueryImpl;
|
||||
|
||||
std::stack<const char*> groupMarkers;
|
||||
|
||||
@@ -134,7 +133,6 @@ id<MTLTexture> getOrCreateEmptyTexture(MetalContext* context);
|
||||
|
||||
bool isInRenderPass(MetalContext* context);
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
void initializeSupportedGpuFamilies(MetalContext* context) {
|
||||
auto& highestSupportedFamily = context->highestSupportedGpuFamily;
|
||||
@@ -145,6 +144,5 @@ bool isInRenderPass(MetalContext* context) {
|
||||
return context->currentRenderPassEncoder != nil;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -31,8 +31,6 @@ namespace backend {
|
||||
|
||||
class MetalPlatform;
|
||||
|
||||
namespace metal {
|
||||
|
||||
class MetalBuffer;
|
||||
struct MetalUniformBuffer;
|
||||
struct MetalContext;
|
||||
@@ -44,31 +42,32 @@ struct UniformBufferState;
|
||||
#endif
|
||||
|
||||
class MetalDriver final : public DriverBase {
|
||||
explicit MetalDriver(backend::MetalPlatform* platform) noexcept;
|
||||
explicit MetalDriver(MetalPlatform* platform) noexcept;
|
||||
~MetalDriver() noexcept override;
|
||||
Dispatcher getDispatcher() const noexcept final;
|
||||
|
||||
public:
|
||||
static Driver* create(backend::MetalPlatform* platform);
|
||||
static Driver* create(MetalPlatform* platform);
|
||||
|
||||
private:
|
||||
|
||||
friend class MetalSwapChain;
|
||||
|
||||
backend::MetalPlatform& mPlatform;
|
||||
MetalPlatform& mPlatform;
|
||||
|
||||
MetalContext* mContext;
|
||||
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
|
||||
// Overrides the default implementation by wrapping the call to fn in an @autoreleasepool block.
|
||||
void execute(std::function<void(void)> fn) noexcept final;
|
||||
void execute(std::function<void(void)> const& fn) noexcept final;
|
||||
|
||||
/*
|
||||
* Driver interface
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
friend class backend::ConcreteDispatcher;
|
||||
friend class ConcreteDispatcher;
|
||||
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
UTILS_ALWAYS_INLINE inline void methodName(paramsDecl);
|
||||
@@ -86,7 +85,7 @@ private:
|
||||
* Memory management
|
||||
*/
|
||||
|
||||
backend::HandleAllocatorMTL mHandleAllocator;
|
||||
HandleAllocatorMTL mHandleAllocator;
|
||||
|
||||
template<typename D>
|
||||
Handle<D> alloc_handle() {
|
||||
@@ -126,7 +125,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -41,22 +41,23 @@ namespace filament {
|
||||
namespace backend {
|
||||
|
||||
Driver* MetalDriverFactory::create(MetalPlatform* const platform) {
|
||||
return metal::MetalDriver::create(platform);
|
||||
return MetalDriver::create(platform);
|
||||
}
|
||||
|
||||
namespace metal {
|
||||
|
||||
UTILS_NOINLINE
|
||||
Driver* MetalDriver::create(MetalPlatform* const platform) {
|
||||
assert_invariant(platform);
|
||||
return new MetalDriver(platform);
|
||||
}
|
||||
|
||||
MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
|
||||
: DriverBase(new ConcreteDispatcher<MetalDriver>()),
|
||||
mPlatform(*platform),
|
||||
mContext(new MetalContext),
|
||||
mHandleAllocator("Handles", FILAMENT_METAL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U) {
|
||||
Dispatcher MetalDriver::getDispatcher() const noexcept {
|
||||
return ConcreteDispatcher<MetalDriver>::make();
|
||||
}
|
||||
|
||||
MetalDriver::MetalDriver(MetalPlatform* platform) noexcept
|
||||
: mPlatform(*platform),
|
||||
mContext(new MetalContext),
|
||||
mHandleAllocator("Handles", FILAMENT_METAL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U) {
|
||||
mContext->driver = this;
|
||||
|
||||
mContext->device = mPlatform.createDevice();
|
||||
@@ -108,7 +109,7 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
|
||||
mContext->blitter = new MetalBlitter(*mContext);
|
||||
|
||||
if (@available(iOS 12, *)) {
|
||||
mContext->timerQueryImpl = new TimerQueryFence(*mContext);
|
||||
mContext->timerQueryImpl = new MetalTimerQueryFence(*mContext);
|
||||
} else {
|
||||
mContext->timerQueryImpl = new TimerQueryNoop();
|
||||
}
|
||||
@@ -149,18 +150,18 @@ void MetalDriver::beginFrame(int64_t monotonic_clock_ns, uint32_t frameId) {
|
||||
}
|
||||
|
||||
void MetalDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
|
||||
backend::FrameScheduledCallback callback, void* user) {
|
||||
FrameScheduledCallback callback, void* user) {
|
||||
auto* swapChain = handle_cast<MetalSwapChain>(sch);
|
||||
swapChain->setFrameScheduledCallback(callback, user);
|
||||
}
|
||||
|
||||
void MetalDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
|
||||
backend::FrameCompletedCallback callback, void* user) {
|
||||
FrameCompletedCallback callback, void* user) {
|
||||
auto* swapChain = handle_cast<MetalSwapChain>(sch);
|
||||
swapChain->setFrameCompletedCallback(callback, user);
|
||||
}
|
||||
|
||||
void MetalDriver::execute(std::function<void(void)> fn) noexcept {
|
||||
void MetalDriver::execute(std::function<void(void)> const& fn) noexcept {
|
||||
@autoreleasepool {
|
||||
fn();
|
||||
}
|
||||
@@ -291,7 +292,7 @@ void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int dum
|
||||
|
||||
void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height,
|
||||
uint8_t samples, backend::MRT color,
|
||||
uint8_t samples, MRT color,
|
||||
TargetBufferInfo depth, TargetBufferInfo stencil) {
|
||||
// Clamp sample count to what the device supports.
|
||||
auto& sc = mContext->sampleCountLookup;
|
||||
@@ -344,7 +345,7 @@ void MetalDriver::createSyncR(Handle<HwSync> sh, int) {
|
||||
}
|
||||
|
||||
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
|
||||
if (UTILS_UNLIKELY(flags & backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) {
|
||||
if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) {
|
||||
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) nativeWindow;
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, pixelBuffer, flags);
|
||||
} else {
|
||||
@@ -358,10 +359,6 @@ void MetalDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, width, height, flags);
|
||||
}
|
||||
|
||||
void MetalDriver::createStreamFromTextureIdR(Handle<HwStream>, intptr_t externalTextureId,
|
||||
uint32_t width, uint32_t height) {
|
||||
}
|
||||
|
||||
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
}
|
||||
@@ -430,10 +427,6 @@ Handle<HwSwapChain> MetalDriver::createSwapChainHeadlessS() noexcept {
|
||||
return alloc_handle<MetalSwapChain>();
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamFromTextureIdS() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwTimerQuery> MetalDriver::createTimerQueryS() noexcept {
|
||||
// The handle must be constructed here, as a synchronous call to getTimerQueryValue might happen
|
||||
// before createTimerQueryR is executed.
|
||||
@@ -569,7 +562,7 @@ Handle<HwStream> MetalDriver::createStreamAcquired() {
|
||||
}
|
||||
|
||||
void MetalDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
|
||||
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
|
||||
CallbackHandler* handler, StreamCallback cb, void* userData) {
|
||||
}
|
||||
|
||||
void MetalDriver::setStreamDimensions(Handle<HwStream> stream, uint32_t width,
|
||||
@@ -581,7 +574,7 @@ int64_t MetalDriver::getStreamTimestamp(Handle<HwStream> stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MetalDriver::updateStreams(backend::DriverApi* driver) {
|
||||
void MetalDriver::updateStreams(DriverApi* driver) {
|
||||
|
||||
}
|
||||
|
||||
@@ -1052,14 +1045,9 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
|
||||
}];
|
||||
}
|
||||
|
||||
void MetalDriver::readStreamPixels(Handle<HwStream> sh, uint32_t x, uint32_t y, uint32_t width,
|
||||
uint32_t height, PixelBufferDescriptor&& data) {
|
||||
|
||||
}
|
||||
|
||||
void MetalDriver::blit(TargetBufferFlags buffers,
|
||||
Handle<HwRenderTarget> dst, backend::Viewport dstRect,
|
||||
Handle<HwRenderTarget> src, backend::Viewport srcRect,
|
||||
Handle<HwRenderTarget> dst, Viewport dstRect,
|
||||
Handle<HwRenderTarget> src, Viewport srcRect,
|
||||
SamplerMagFilter filter) {
|
||||
// If we're the in middle of a render pass, finish it.
|
||||
// This condition should only occur during copyFrame. It's okay to end the render pass because
|
||||
@@ -1166,7 +1154,7 @@ void MetalDriver::blit(TargetBufferFlags buffers,
|
||||
mContext->blitter->blit(getPendingCommandBuffer(mContext), args);
|
||||
}
|
||||
|
||||
void MetalDriver::draw(backend::PipelineState ps, Handle<HwRenderPrimitive> rph, uint32_t instanceCount) {
|
||||
void MetalDriver::draw(PipelineState ps, Handle<HwRenderPrimitive> rph, uint32_t instanceCount) {
|
||||
ASSERT_PRECONDITION(mContext->currentRenderPassEncoder != nullptr,
|
||||
"Attempted to draw without a valid command encoder.");
|
||||
auto primitive = handle_cast<MetalRenderPrimitive>(rph);
|
||||
@@ -1196,7 +1184,7 @@ void MetalDriver::draw(backend::PipelineState ps, Handle<HwRenderPrimitive> rph,
|
||||
if (depthAttachment) {
|
||||
depthPixelFormat = depthAttachment.getPixelFormat();
|
||||
}
|
||||
metal::PipelineState pipelineState {
|
||||
MetalPipelineState pipelineState {
|
||||
.vertexFunction = program->vertexFunction,
|
||||
.fragmentFunction = program->fragmentFunction,
|
||||
.vertexDescription = primitive->vertexDescription,
|
||||
@@ -1304,15 +1292,15 @@ void MetalDriver::draw(backend::PipelineState ps, Handle<HwRenderPrimitive> rph,
|
||||
return mContext->samplerStateCache.getOrCreateState(s);
|
||||
};
|
||||
|
||||
id<MTLTexture> texturesToBindVertex[backend::MAX_VERTEX_SAMPLER_COUNT] = {};
|
||||
id<MTLSamplerState> samplersToBindVertex[backend::MAX_VERTEX_SAMPLER_COUNT] = {};
|
||||
id<MTLTexture> texturesToBindVertex[MAX_VERTEX_SAMPLER_COUNT] = {};
|
||||
id<MTLSamplerState> samplersToBindVertex[MAX_VERTEX_SAMPLER_COUNT] = {};
|
||||
|
||||
enumerateSamplerGroups(program, ShaderType::VERTEX,
|
||||
[this, &getTextureToBind, &getSamplerToBind, &texturesToBindVertex, &samplersToBindVertex](
|
||||
const SamplerGroup::Sampler* sampler, uint8_t binding) {
|
||||
// We currently only support a max of MAX_VERTEX_SAMPLER_COUNT samplers. Ignore any additional
|
||||
// samplers that may be bound.
|
||||
if (binding >= backend::MAX_VERTEX_SAMPLER_COUNT) {
|
||||
if (binding >= MAX_VERTEX_SAMPLER_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1336,21 +1324,21 @@ void MetalDriver::draw(backend::PipelineState ps, Handle<HwRenderPrimitive> rph,
|
||||
}
|
||||
}
|
||||
|
||||
NSRange vertexSamplerRange = NSMakeRange(0, backend::MAX_VERTEX_SAMPLER_COUNT);
|
||||
NSRange vertexSamplerRange = NSMakeRange(0, MAX_VERTEX_SAMPLER_COUNT);
|
||||
[mContext->currentRenderPassEncoder setVertexTextures:texturesToBindVertex
|
||||
withRange:vertexSamplerRange];
|
||||
[mContext->currentRenderPassEncoder setVertexSamplerStates:samplersToBindVertex
|
||||
withRange:vertexSamplerRange];
|
||||
|
||||
id<MTLTexture> texturesToBindFragment[backend::MAX_FRAGMENT_SAMPLER_COUNT] = {};
|
||||
id<MTLSamplerState> samplersToBindFragment[backend::MAX_FRAGMENT_SAMPLER_COUNT] = {};
|
||||
id<MTLTexture> texturesToBindFragment[MAX_FRAGMENT_SAMPLER_COUNT] = {};
|
||||
id<MTLSamplerState> samplersToBindFragment[MAX_FRAGMENT_SAMPLER_COUNT] = {};
|
||||
|
||||
enumerateSamplerGroups(program, ShaderType::FRAGMENT,
|
||||
[this, &getTextureToBind, &getSamplerToBind, &texturesToBindFragment, &samplersToBindFragment](
|
||||
const SamplerGroup::Sampler* sampler, uint8_t binding) {
|
||||
// We currently only support a max of MAX_FRAGMENT_SAMPLER_COUNT samplers. Ignore any additional
|
||||
// samplers that may be bound.
|
||||
if (binding >= backend::MAX_FRAGMENT_SAMPLER_COUNT) {
|
||||
if (binding >= MAX_FRAGMENT_SAMPLER_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1374,7 +1362,7 @@ void MetalDriver::draw(backend::PipelineState ps, Handle<HwRenderPrimitive> rph,
|
||||
}
|
||||
}
|
||||
|
||||
NSRange fragmentSamplerRange = NSMakeRange(0, backend::MAX_FRAGMENT_SAMPLER_COUNT);
|
||||
NSRange fragmentSamplerRange = NSMakeRange(0, MAX_FRAGMENT_SAMPLER_COUNT);
|
||||
[mContext->currentRenderPassEncoder setFragmentTextures:texturesToBindFragment
|
||||
withRange:fragmentSamplerRange];
|
||||
[mContext->currentRenderPassEncoder setFragmentSamplerStates:samplersToBindFragment
|
||||
@@ -1479,10 +1467,8 @@ void MetalDriver::enumerateBoundUniformBuffers(
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
|
||||
// explicit instantiation of the Dispatcher
|
||||
template class ConcreteDispatcher<metal::MetalDriver>;
|
||||
template class ConcreteDispatcher<MetalDriver>;
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -24,7 +24,7 @@ class Driver;
|
||||
|
||||
class MetalDriverFactory {
|
||||
public:
|
||||
static Driver* create(backend::MetalPlatform* platform);
|
||||
static Driver* create(MetalPlatform* platform);
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
struct MetalContext;
|
||||
|
||||
@@ -405,7 +404,6 @@ inline MTLTextureSwizzleChannels getSwizzleChannels(TextureSwizzle r, TextureSwi
|
||||
getSwizzle(a));
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
MTLPixelFormat getMetalFormat(MetalContext* context, TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
@@ -207,6 +206,5 @@ MTLPixelFormat getMetalFormat(MetalContext* context, TextureFormat format) noexc
|
||||
return MTLPixelFormatInvalid;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
struct MetalContext;
|
||||
|
||||
@@ -129,7 +128,6 @@ private:
|
||||
} mSwizzle;
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
static const auto cvBufferDeleter = [](const void* buffer) {
|
||||
CVBufferRelease((CVMetalTextureRef) buffer);
|
||||
@@ -300,6 +299,5 @@ id<MTLCommandBuffer> MetalExternalImage::encodeColorConversionPass(id<MTLTexture
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
class MetalSwapChain : public HwSwapChain {
|
||||
public:
|
||||
@@ -357,7 +356,6 @@ struct MetalTimerQuery : public HwTimerQuery {
|
||||
std::shared_ptr<Status> status;
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) {
|
||||
NSUInteger u = 0;
|
||||
@@ -68,9 +67,8 @@ MetalSwapChain::MetalSwapChain(MetalContext& context, CAMetalLayer* nativeWindow
|
||||
}
|
||||
|
||||
// Needed so we can use the SwapChain as a blit source.
|
||||
if (flags & SwapChain::CONFIG_READABLE) {
|
||||
nativeWindow.framebufferOnly = NO;
|
||||
}
|
||||
// Also needed for rendering directly into the SwapChain during refraction.
|
||||
nativeWindow.framebufferOnly = NO;
|
||||
|
||||
layer.device = context.device;
|
||||
}
|
||||
@@ -81,7 +79,7 @@ MetalSwapChain::MetalSwapChain(MetalContext& context, int32_t width, int32_t hei
|
||||
|
||||
MetalSwapChain::MetalSwapChain(MetalContext& context, CVPixelBufferRef pixelBuffer, uint64_t flags)
|
||||
: context(context), externalImage(context), type(SwapChainType::CVPIXELBUFFERREF) {
|
||||
assert_invariant(flags & backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER);
|
||||
assert_invariant(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER);
|
||||
MetalExternalImage::assertWritableImage(pixelBuffer);
|
||||
externalImage.set(pixelBuffer);
|
||||
assert_invariant(externalImage.isValid());
|
||||
@@ -224,7 +222,7 @@ void MetalSwapChain::scheduleFrameScheduledCallback() {
|
||||
}
|
||||
|
||||
assert_invariant(drawable);
|
||||
backend::FrameScheduledCallback callback = frameScheduledCallback;
|
||||
FrameScheduledCallback callback = frameScheduledCallback;
|
||||
// This block strongly captures drawable to keep it alive until the handler executes.
|
||||
// We cannot simply reference this->drawable inside the block because the block would then only
|
||||
// capture the _this_ pointer (MetalSwapChain*) instead of the drawable.
|
||||
@@ -245,12 +243,12 @@ void MetalSwapChain::scheduleFrameCompletedCallback() {
|
||||
return;
|
||||
}
|
||||
|
||||
backend::FrameCompletedCallback callback = frameCompletedCallback;
|
||||
FrameCompletedCallback callback = frameCompletedCallback;
|
||||
void* userData = frameCompletedUserData;
|
||||
[getPendingCommandBuffer(&context) addCompletedHandler:^(id<MTLCommandBuffer> cb) {
|
||||
struct CallbackData {
|
||||
void* userData;
|
||||
backend::FrameCompletedCallback callback;
|
||||
FrameCompletedCallback callback;
|
||||
};
|
||||
CallbackData* data = new CallbackData();
|
||||
data->userData = userData;
|
||||
@@ -369,7 +367,7 @@ MetalProgram::MetalProgram(id<MTLDevice> device, const Program& program) noexcep
|
||||
*shaderFunctions[i] = [library newFunctionWithName:@"main0"];
|
||||
}
|
||||
|
||||
// All stages of the program have compiled successfuly, this is a valid program.
|
||||
// All stages of the program have compiled successfully, this is a valid program.
|
||||
isValid = true;
|
||||
|
||||
// This calculates Metal resource binding indices. Filament's sampler bindings range from 0-31
|
||||
@@ -1024,6 +1022,5 @@ FenceStatus MetalFence::wait(uint64_t timeoutNs) {
|
||||
return FenceStatus::ERROR;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
bool MetalResourceTracker::trackResource(CommandBuffer buffer, Resource resource,
|
||||
ResourceDeleter deleter) {
|
||||
@@ -53,6 +52,5 @@ void MetalResourceTracker::clearResources(CommandBuffer buffer) {
|
||||
mResources.erase(found);
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
/**
|
||||
* MetalResourceTracker is a simple utility that maps individual command buffers to a set of
|
||||
@@ -76,7 +75,6 @@ private:
|
||||
std::mutex mMutex;
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -31,24 +31,21 @@
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
inline bool operator==(const backend::SamplerParams& lhs, const backend::SamplerParams& rhs) {
|
||||
inline bool operator==(const SamplerParams& lhs, const SamplerParams& rhs) {
|
||||
return lhs.u == rhs.u;
|
||||
}
|
||||
|
||||
namespace metal {
|
||||
|
||||
static constexpr uint32_t MAX_VERTEX_ATTRIBUTE_COUNT = backend::MAX_VERTEX_ATTRIBUTE_COUNT;
|
||||
static constexpr uint32_t SAMPLER_GROUP_COUNT = Program::BINDING_COUNT;
|
||||
static constexpr uint32_t SAMPLER_BINDING_COUNT = backend::MAX_SAMPLER_COUNT;
|
||||
static constexpr uint32_t SAMPLER_BINDING_COUNT = MAX_SAMPLER_COUNT;
|
||||
static constexpr uint32_t VERTEX_BUFFER_START = Program::BINDING_COUNT;
|
||||
|
||||
// The "zero" buffer is a small buffer for missing attributes that resides in the vertex slot
|
||||
// immediately following any user-provided vertex buffers.
|
||||
static constexpr uint32_t ZERO_VERTEX_BUFFER = backend::MAX_VERTEX_BUFFER_COUNT;
|
||||
static constexpr uint32_t ZERO_VERTEX_BUFFER = MAX_VERTEX_BUFFER_COUNT;
|
||||
|
||||
// The total number of vertex buffer "slots" that the Metal backend can bind.
|
||||
// + 1 to account for the zero buffer.
|
||||
static constexpr uint32_t VERTEX_BUFFER_COUNT = backend::MAX_VERTEX_BUFFER_COUNT + 1;
|
||||
static constexpr uint32_t VERTEX_BUFFER_COUNT = MAX_VERTEX_BUFFER_COUNT + 1;
|
||||
|
||||
// Forward declarations necessary here, definitions at end of file.
|
||||
inline bool operator==(const MTLViewport& lhs, const MTLViewport& rhs);
|
||||
@@ -173,7 +170,7 @@ private:
|
||||
};
|
||||
|
||||
// StateTracker keeps track of state changes made to a Metal command encoder.
|
||||
// Different kinds of state, like pipeline state, uniform buffer state, etc, are passed to the
|
||||
// Different kinds of state, like pipeline state, uniform buffer state, etc., are passed to the
|
||||
// current Metal command encoder and persist throughout the lifetime of the encoder (a frame).
|
||||
// StateTracker is used to prevent calling redundant state change methods.
|
||||
template<typename StateType>
|
||||
@@ -212,7 +209,7 @@ private:
|
||||
|
||||
// Pipeline state
|
||||
|
||||
struct PipelineState {
|
||||
struct MetalPipelineState {
|
||||
id<MTLFunction> vertexFunction = nil; // 8 bytes
|
||||
id<MTLFunction> fragmentFunction = nil; // 8 bytes
|
||||
VertexDescription vertexDescription; // 528 bytes
|
||||
@@ -223,7 +220,7 @@ struct PipelineState {
|
||||
bool colorWrite = true; // 1 byte
|
||||
char padding[7] = { 0 }; // 7 bytes
|
||||
|
||||
bool operator==(const PipelineState& rhs) const noexcept {
|
||||
bool operator==(const MetalPipelineState& rhs) const noexcept {
|
||||
return (
|
||||
this->vertexFunction == rhs.vertexFunction &&
|
||||
this->fragmentFunction == rhs.fragmentFunction &&
|
||||
@@ -237,23 +234,23 @@ struct PipelineState {
|
||||
);
|
||||
}
|
||||
|
||||
bool operator!=(const PipelineState& rhs) const noexcept {
|
||||
bool operator!=(const MetalPipelineState& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
// This assert checks that the struct is the size we expect without any "hidden" padding bytes
|
||||
// inserted by the compiler.
|
||||
static_assert(sizeof(PipelineState) == 688, "PipelineState unexpected size.");
|
||||
static_assert(sizeof(MetalPipelineState) == 688, "MetalPipelineState unexpected size.");
|
||||
|
||||
struct PipelineStateCreator {
|
||||
id<MTLRenderPipelineState> operator()(id<MTLDevice> device, const PipelineState& state)
|
||||
id<MTLRenderPipelineState> operator()(id<MTLDevice> device, const MetalPipelineState& state)
|
||||
noexcept;
|
||||
};
|
||||
|
||||
using PipelineStateTracker = StateTracker<PipelineState>;
|
||||
using PipelineStateTracker = StateTracker<MetalPipelineState>;
|
||||
|
||||
using PipelineStateCache = StateCache<PipelineState, id<MTLRenderPipelineState>,
|
||||
using PipelineStateCache = StateCache<MetalPipelineState, id<MTLRenderPipelineState>,
|
||||
PipelineStateCreator>;
|
||||
|
||||
// Depth-stencil State
|
||||
@@ -315,7 +312,7 @@ using UniformBufferStateTracker = StateTracker<UniformBufferState>;
|
||||
// Sampler states
|
||||
|
||||
struct SamplerState {
|
||||
backend::SamplerParams samplerParams;
|
||||
SamplerParams samplerParams;
|
||||
uint32_t minLod = 0;
|
||||
uint32_t maxLod = UINT_MAX;
|
||||
|
||||
@@ -343,7 +340,6 @@ using SamplerStateCache = StateCache<SamplerState, id<MTLSamplerState>, SamplerS
|
||||
using CullModeStateTracker = StateTracker<MTLCullMode>;
|
||||
using WindingStateTracker = StateTracker<MTLWinding>;
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
id<MTLRenderPipelineState> PipelineStateCreator::operator()(id<MTLDevice> device,
|
||||
const PipelineState& state) noexcept {
|
||||
const MetalPipelineState& state) noexcept {
|
||||
MTLRenderPipelineDescriptor* descriptor = [MTLRenderPipelineDescriptor new];
|
||||
|
||||
// Shader Functions
|
||||
@@ -105,7 +104,7 @@ id<MTLDepthStencilState> DepthStateCreator::operator()(id<MTLDevice> device,
|
||||
|
||||
id<MTLSamplerState> SamplerStateCreator::operator()(id<MTLDevice> device,
|
||||
const SamplerState& state) noexcept {
|
||||
backend::SamplerParams params = state.samplerParams;
|
||||
SamplerParams params = state.samplerParams;
|
||||
MTLSamplerDescriptor* samplerDescriptor = [MTLSamplerDescriptor new];
|
||||
samplerDescriptor.minFilter = getFilter(params.filterMin);
|
||||
samplerDescriptor.magFilter = getFilter(params.filterMag);
|
||||
@@ -133,6 +132,5 @@ id<MTLSamplerState> SamplerStateCreator::operator()(id<MTLDevice> device,
|
||||
return [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -23,14 +23,13 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
struct MetalTimerQuery;
|
||||
struct MetalContext;
|
||||
|
||||
class TimerQueryInterface {
|
||||
class MetalTimerQueryInterface {
|
||||
public:
|
||||
virtual ~TimerQueryInterface();
|
||||
virtual ~MetalTimerQueryInterface();
|
||||
virtual void beginTimeElapsedQuery(MetalTimerQuery* query) = 0;
|
||||
virtual void endTimeElapsedQuery(MetalTimerQuery* query) = 0;
|
||||
virtual bool getQueryResult(MetalTimerQuery* query, uint64_t* outElapsedTime) = 0;
|
||||
@@ -41,9 +40,9 @@ protected:
|
||||
|
||||
// Uses MTLSharedEvents to implement timer queries.
|
||||
// Only available on >= iOS 12.0.
|
||||
class API_AVAILABLE(ios(12.0)) TimerQueryFence : public TimerQueryInterface {
|
||||
class API_AVAILABLE(ios(12.0)) MetalTimerQueryFence : public MetalTimerQueryInterface {
|
||||
public:
|
||||
explicit TimerQueryFence(MetalContext& context) : mContext(context) {}
|
||||
explicit MetalTimerQueryFence(MetalContext& context) : mContext(context) {}
|
||||
|
||||
void beginTimeElapsedQuery(MetalTimerQuery* query) override;
|
||||
void endTimeElapsedQuery(MetalTimerQuery* query) override;
|
||||
@@ -53,14 +52,13 @@ private:
|
||||
MetalContext& mContext;
|
||||
};
|
||||
|
||||
class TimerQueryNoop : public TimerQueryInterface {
|
||||
class TimerQueryNoop : public MetalTimerQueryInterface {
|
||||
public:
|
||||
void beginTimeElapsedQuery(MetalTimerQuery* query) override {}
|
||||
void endTimeElapsedQuery(MetalTimerQuery* query) override {}
|
||||
bool getQueryResult(MetalTimerQuery* query, uint64_t* outElapsedTime) override;
|
||||
};
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -20,11 +20,10 @@
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
TimerQueryInterface::~TimerQueryInterface() = default;
|
||||
MetalTimerQueryInterface::~MetalTimerQueryInterface() = default;
|
||||
|
||||
void TimerQueryFence::beginTimeElapsedQuery(MetalTimerQuery* query) {
|
||||
void MetalTimerQueryFence::beginTimeElapsedQuery(MetalTimerQuery* query) {
|
||||
auto* fence = new MetalFence(mContext);
|
||||
fence->encode();
|
||||
query->status->elapsed = 0;
|
||||
@@ -41,7 +40,7 @@ void TimerQueryFence::beginTimeElapsedQuery(MetalTimerQuery* query) {
|
||||
});
|
||||
}
|
||||
|
||||
void TimerQueryFence::endTimeElapsedQuery(MetalTimerQuery* query) {
|
||||
void MetalTimerQueryFence::endTimeElapsedQuery(MetalTimerQuery* query) {
|
||||
auto* fence = new MetalFence(mContext);
|
||||
fence->encode();
|
||||
|
||||
@@ -57,7 +56,7 @@ void TimerQueryFence::endTimeElapsedQuery(MetalTimerQuery* query) {
|
||||
});
|
||||
}
|
||||
|
||||
bool TimerQueryFence::getQueryResult(MetalTimerQuery* query, uint64_t* outElapsedTime) {
|
||||
bool MetalTimerQueryFence::getQueryResult(MetalTimerQuery* query, uint64_t* outElapsedTime) {
|
||||
if (!query->status->available.load()) {
|
||||
return false;
|
||||
}
|
||||
@@ -71,6 +70,5 @@ bool TimerQueryNoop::getQueryResult(MetalTimerQuery* query, uint64_t* outElapsed
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace metal
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
namespace filament::backend::metal {
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
* Creates a texture view of the passed-in texture with the given swizzle. If swizzle is the default
|
||||
@@ -42,6 +42,6 @@ id<MTLTexture> createTextureViewWithSwizzle(id<MTLTexture> texture,
|
||||
*/
|
||||
id<MTLTexture> createTextureViewWithSingleSlice(id<MTLTexture> texture, NSUInteger slice);
|
||||
|
||||
} // namespace filament::backend::metal
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif //TNT_FILAMENT_DRIVER_METALUTILS_H
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "MetalUtils.h"
|
||||
|
||||
namespace filament::backend::metal {
|
||||
namespace filament::backend {
|
||||
|
||||
id<MTLTexture> createTextureViewWithSwizzle(id<MTLTexture> texture,
|
||||
MTLTextureSwizzleChannels swizzle) {
|
||||
@@ -48,4 +48,4 @@ id<MTLTexture> createTextureViewWithSingleSlice(id<MTLTexture> texture, NSUInteg
|
||||
slices:NSMakeRange(slice, 1)];
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -17,20 +17,21 @@
|
||||
#include "noop/NoopDriver.h"
|
||||
#include "CommandStreamDispatcher.h"
|
||||
|
||||
namespace filament {
|
||||
|
||||
using namespace backend;
|
||||
namespace filament::backend {
|
||||
|
||||
Driver* NoopDriver::create() {
|
||||
return new NoopDriver();
|
||||
}
|
||||
|
||||
NoopDriver::NoopDriver() noexcept : DriverBase(new ConcreteDispatcher<NoopDriver>()) {
|
||||
}
|
||||
NoopDriver::NoopDriver() noexcept = default;
|
||||
|
||||
NoopDriver::~NoopDriver() noexcept = default;
|
||||
|
||||
backend::ShaderModel NoopDriver::getShaderModel() const noexcept {
|
||||
Dispatcher NoopDriver::getDispatcher() const noexcept {
|
||||
return ConcreteDispatcher<NoopDriver>::make();
|
||||
}
|
||||
|
||||
ShaderModel NoopDriver::getShaderModel() const noexcept {
|
||||
#if defined(__ANDROID__) || defined(IOS) || defined(__EMSCRIPTEN__)
|
||||
return ShaderModel::GL_ES_30;
|
||||
#else
|
||||
@@ -39,7 +40,7 @@ backend::ShaderModel NoopDriver::getShaderModel() const noexcept {
|
||||
}
|
||||
|
||||
// explicit instantiation of the Dispatcher
|
||||
template class backend::ConcreteDispatcher<NoopDriver>;
|
||||
template class ConcreteDispatcher<NoopDriver>;
|
||||
|
||||
|
||||
void NoopDriver::terminate() {
|
||||
@@ -52,12 +53,12 @@ void NoopDriver::beginFrame(int64_t monotonic_clock_ns, uint32_t frameId) {
|
||||
}
|
||||
|
||||
void NoopDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
|
||||
backend::FrameScheduledCallback callback, void* user) {
|
||||
FrameScheduledCallback callback, void* user) {
|
||||
|
||||
}
|
||||
|
||||
void NoopDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
|
||||
backend::FrameCompletedCallback callback, void* user) {
|
||||
FrameCompletedCallback callback, void* user) {
|
||||
|
||||
}
|
||||
|
||||
@@ -118,7 +119,7 @@ Handle<HwStream> NoopDriver::createStreamAcquired() {
|
||||
}
|
||||
|
||||
void NoopDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
|
||||
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
|
||||
CallbackHandler* handler, StreamCallback cb, void* userData) {
|
||||
}
|
||||
|
||||
void NoopDriver::setStreamDimensions(Handle<HwStream> sh, uint32_t width, uint32_t height) {
|
||||
@@ -148,7 +149,7 @@ bool NoopDriver::isTextureSwizzleSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NoopDriver::isTextureFormatMipmappable(backend::TextureFormat format) {
|
||||
bool NoopDriver::isTextureFormatMipmappable(TextureFormat format) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -181,7 +182,7 @@ math::float2 NoopDriver::getClipSpaceParams() {
|
||||
}
|
||||
|
||||
uint8_t NoopDriver::getMaxDrawBuffers() {
|
||||
return backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
|
||||
return MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
|
||||
}
|
||||
|
||||
void NoopDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor&& p,
|
||||
@@ -307,14 +308,9 @@ void NoopDriver::readPixels(Handle<HwRenderTarget> src,
|
||||
scheduleDestroy(std::move(p));
|
||||
}
|
||||
|
||||
void NoopDriver::readStreamPixels(Handle<HwStream> sh, uint32_t x, uint32_t y, uint32_t width,
|
||||
uint32_t height, PixelBufferDescriptor&& p) {
|
||||
scheduleDestroy(std::move(p));
|
||||
}
|
||||
|
||||
void NoopDriver::blit(TargetBufferFlags buffers,
|
||||
Handle<HwRenderTarget> dst, backend::Viewport dstRect,
|
||||
Handle<HwRenderTarget> src, backend::Viewport srcRect,
|
||||
Handle<HwRenderTarget> dst, Viewport dstRect,
|
||||
Handle<HwRenderTarget> src, Viewport srcRect,
|
||||
SamplerMagFilter filter) {
|
||||
}
|
||||
|
||||
|
||||
@@ -14,32 +14,33 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_NOOPDRIVER_H
|
||||
#define TNT_FILAMENT_DRIVER_NOOPDRIVER_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_NOOPDRIVER_H
|
||||
#define TNT_FILAMENT_BACKEND_NOOPDRIVER_H
|
||||
|
||||
#include "private/backend/Driver.h"
|
||||
#include "DriverBase.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
class NoopDriver final : public backend::DriverBase {
|
||||
class NoopDriver final : public DriverBase {
|
||||
NoopDriver() noexcept;
|
||||
~NoopDriver() noexcept override;
|
||||
Dispatcher getDispatcher() const noexcept final;
|
||||
|
||||
public:
|
||||
static backend::Driver* create();
|
||||
static Driver* create();
|
||||
|
||||
private:
|
||||
backend::ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
|
||||
/*
|
||||
* Driver interface
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
friend class backend::ConcreteDispatcher;
|
||||
friend class ConcreteDispatcher;
|
||||
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
UTILS_ALWAYS_INLINE inline void methodName(paramsDecl);
|
||||
@@ -57,4 +58,4 @@ private:
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_NOOPDRIVER_H
|
||||
#endif // TNT_FILAMENT_BACKEND_NOOPDRIVER_H
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
#include "noop/NoopDriver.h"
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
backend::Driver* PlatformNoop::createDriver(void* const sharedGLContext) noexcept {
|
||||
Driver* PlatformNoop::createDriver(void* const sharedGLContext) noexcept {
|
||||
return NoopDriver::create();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_NOOP_PLATFORM_NOOP_H
|
||||
#define TNT_FILAMENT_DRIVER_NOOP_PLATFORM_NOOP_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_NOOP_PLATFORM_NOOP_H
|
||||
#define TNT_FILAMENT_BACKEND_NOOP_PLATFORM_NOOP_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
class PlatformNoop final : public backend::DefaultPlatform {
|
||||
class PlatformNoop final : public DefaultPlatform {
|
||||
public:
|
||||
|
||||
int getOSVersion() const noexcept final { return 0; }
|
||||
@@ -31,9 +31,9 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
backend::Driver* createDriver(void* sharedContext) noexcept override;
|
||||
Driver* createDriver(void* sharedContext) noexcept override;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_NOOP_PLATFORM_NOOP_H
|
||||
#endif // TNT_FILAMENT_BACKEND_NOOP_PLATFORM_NOOP_H
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "private/backend/Driver.h"
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
using namespace backend;
|
||||
using namespace utils;
|
||||
@@ -121,5 +121,21 @@ void assertFramebufferStatus(io::ostream& out, GLenum target, const char* functi
|
||||
}
|
||||
}
|
||||
|
||||
bool unordered_string_set::has(std::string_view str) const noexcept {
|
||||
return find(str) != end();
|
||||
}
|
||||
|
||||
unordered_string_set split(const char* extensions) noexcept {
|
||||
unordered_string_set set;
|
||||
std::string_view string(extensions);
|
||||
do {
|
||||
auto p = string.find(' ');
|
||||
p = (p == std::string_view::npos ? string.length() : p);
|
||||
set.emplace(string.data(), p);
|
||||
string.remove_prefix(p == string.length() ? p : p + 1);
|
||||
} while(!string.empty());
|
||||
return set;
|
||||
}
|
||||
|
||||
} // namespace GLUtils
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -14,22 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_GLUTILS_H
|
||||
#define TNT_FILAMENT_DRIVER_GLUTILS_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_GLUTILS_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_GLUTILS_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gl_headers.h"
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
namespace GLUtils {
|
||||
|
||||
const char* getGLError(GLenum error) noexcept;
|
||||
@@ -44,15 +44,12 @@ void assertFramebufferStatus(utils::io::ostream& out, GLenum target, const char*
|
||||
# define CHECK_GL_ERROR(out)
|
||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target)
|
||||
#else
|
||||
# ifdef _MSC_VER
|
||||
# define __PRETTY_FUNCTION__ __FUNCSIG__
|
||||
# endif
|
||||
# define CHECK_GL_ERROR(out) { GLUtils::assertGLError(out, __PRETTY_FUNCTION__, __LINE__); }
|
||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __PRETTY_FUNCTION__, __LINE__); }
|
||||
# define CHECK_GL_ERROR(out) { GLUtils::assertGLError(out, __func__, __LINE__); }
|
||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __func__, __LINE__); }
|
||||
#endif
|
||||
|
||||
constexpr inline GLuint getComponentCount(backend::ElementType type) noexcept {
|
||||
using ElementType = backend::ElementType;
|
||||
constexpr inline GLuint getComponentCount(ElementType type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
case ElementType::BYTE:
|
||||
case ElementType::UBYTE:
|
||||
@@ -91,35 +88,35 @@ constexpr inline GLuint getComponentCount(backend::ElementType type) noexcept {
|
||||
// Our enums to GLenum conversions
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
constexpr inline GLbitfield getAttachmentBitfield(backend::TargetBufferFlags flags) noexcept {
|
||||
constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
|
||||
GLbitfield mask = 0;
|
||||
if (any(flags & backend::TargetBufferFlags::COLOR_ALL)) {
|
||||
if (any(flags & TargetBufferFlags::COLOR_ALL)) {
|
||||
mask |= (GLbitfield)GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (any(flags & backend::TargetBufferFlags::DEPTH)) {
|
||||
if (any(flags & TargetBufferFlags::DEPTH)) {
|
||||
mask |= (GLbitfield)GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
if (any(flags & backend::TargetBufferFlags::STENCIL)) {
|
||||
if (any(flags & TargetBufferFlags::STENCIL)) {
|
||||
mask |= (GLbitfield)GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBufferUsage(backend::BufferUsage usage) noexcept {
|
||||
constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
switch (usage) {
|
||||
case backend::BufferUsage::STATIC:
|
||||
case BufferUsage::STATIC:
|
||||
return GL_STATIC_DRAW;
|
||||
case backend::BufferUsage::DYNAMIC:
|
||||
case backend::BufferUsage::STREAM:
|
||||
case BufferUsage::DYNAMIC:
|
||||
case BufferUsage::STREAM:
|
||||
return GL_DYNAMIC_DRAW;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBufferBindingType(backend::BufferObjectBinding bindingType) noexcept {
|
||||
constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
|
||||
switch (bindingType) {
|
||||
case backend::BufferObjectBinding::VERTEX:
|
||||
case BufferObjectBinding::VERTEX:
|
||||
return GL_ARRAY_BUFFER;
|
||||
case backend::BufferObjectBinding::UNIFORM:
|
||||
case BufferObjectBinding::UNIFORM:
|
||||
return GL_UNIFORM_BUFFER;
|
||||
}
|
||||
}
|
||||
@@ -128,8 +125,8 @@ constexpr inline GLboolean getNormalization(bool normalized) noexcept {
|
||||
return GLboolean(normalized ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getComponentType(backend::ElementType type) noexcept {
|
||||
using ElementType = backend::ElementType;
|
||||
constexpr inline GLenum getComponentType(ElementType type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
case ElementType::BYTE:
|
||||
case ElementType::BYTE2:
|
||||
@@ -173,8 +170,8 @@ constexpr inline GLenum getCubemapTarget(uint16_t layer) noexcept {
|
||||
return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getWrapMode(backend::SamplerWrapMode mode) noexcept {
|
||||
using SamplerWrapMode = backend::SamplerWrapMode;
|
||||
constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
using SamplerWrapMode = SamplerWrapMode;
|
||||
switch (mode) {
|
||||
case SamplerWrapMode::REPEAT:
|
||||
return GL_REPEAT;
|
||||
@@ -185,8 +182,8 @@ constexpr inline GLenum getWrapMode(backend::SamplerWrapMode mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureFilter(backend::SamplerMinFilter filter) noexcept {
|
||||
using SamplerMinFilter = backend::SamplerMinFilter;
|
||||
constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
using SamplerMinFilter = SamplerMinFilter;
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
case SamplerMinFilter::LINEAR:
|
||||
@@ -200,13 +197,13 @@ constexpr inline GLenum getTextureFilter(backend::SamplerMinFilter filter) noexc
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureFilter(backend::SamplerMagFilter filter) noexcept {
|
||||
constexpr inline GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
|
||||
return GL_NEAREST + GLenum(filter);
|
||||
}
|
||||
|
||||
|
||||
constexpr inline GLenum getBlendEquationMode(backend::BlendEquation mode) noexcept {
|
||||
using BlendEquation = backend::BlendEquation;
|
||||
constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
using BlendEquation = BlendEquation;
|
||||
switch (mode) {
|
||||
case BlendEquation::ADD: return GL_FUNC_ADD;
|
||||
case BlendEquation::SUBTRACT: return GL_FUNC_SUBTRACT;
|
||||
@@ -216,8 +213,8 @@ constexpr inline GLenum getBlendEquationMode(backend::BlendEquation mode) noexce
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBlendFunctionMode(backend::BlendFunction mode) noexcept {
|
||||
using BlendFunction = backend::BlendFunction;
|
||||
constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
using BlendFunction = BlendFunction;
|
||||
switch (mode) {
|
||||
case BlendFunction::ZERO: return GL_ZERO;
|
||||
case BlendFunction::ONE: return GL_ONE;
|
||||
@@ -233,13 +230,13 @@ constexpr inline GLenum getBlendFunctionMode(backend::BlendFunction mode) noexce
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureCompareMode(backend::SamplerCompareMode mode) noexcept {
|
||||
return mode == backend::SamplerCompareMode::NONE ?
|
||||
constexpr inline GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
|
||||
return mode == SamplerCompareMode::NONE ?
|
||||
GL_NONE : GL_COMPARE_REF_TO_TEXTURE;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureCompareFunc(backend::SamplerCompareFunc func) noexcept {
|
||||
using SamplerCompareFunc = backend::SamplerCompareFunc;
|
||||
constexpr inline GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
using SamplerCompareFunc = SamplerCompareFunc;
|
||||
switch (func) {
|
||||
case SamplerCompareFunc::LE: return GL_LEQUAL;
|
||||
case SamplerCompareFunc::GE: return GL_GEQUAL;
|
||||
@@ -252,12 +249,12 @@ constexpr inline GLenum getTextureCompareFunc(backend::SamplerCompareFunc func)
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getDepthFunc(backend::SamplerCompareFunc func) noexcept {
|
||||
constexpr inline GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
|
||||
return getTextureCompareFunc(func);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getFormat(backend::PixelDataFormat format) noexcept {
|
||||
using PixelDataFormat = backend::PixelDataFormat;
|
||||
constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
using PixelDataFormat = PixelDataFormat;
|
||||
switch (format) {
|
||||
case PixelDataFormat::R: return GL_RED;
|
||||
case PixelDataFormat::R_INTEGER: return GL_RED_INTEGER;
|
||||
@@ -274,8 +271,8 @@ constexpr inline GLenum getFormat(backend::PixelDataFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getType(backend::PixelDataType type) noexcept {
|
||||
using PixelDataType = backend::PixelDataType;
|
||||
constexpr inline GLenum getType(PixelDataType type) noexcept {
|
||||
using PixelDataType = PixelDataType;
|
||||
switch (type) {
|
||||
case PixelDataType::UBYTE: return GL_UNSIGNED_BYTE;
|
||||
case PixelDataType::BYTE: return GL_BYTE;
|
||||
@@ -292,8 +289,8 @@ constexpr inline GLenum getType(backend::PixelDataType type) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getSwizzleChannel(backend::TextureSwizzle c) noexcept {
|
||||
using TextureSwizzle = backend::TextureSwizzle;
|
||||
constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
using TextureSwizzle = TextureSwizzle;
|
||||
switch (c) {
|
||||
case TextureSwizzle::SUBSTITUTE_ZERO:
|
||||
return GL_ZERO;
|
||||
@@ -313,8 +310,8 @@ constexpr inline GLenum getSwizzleChannel(backend::TextureSwizzle c) noexcept {
|
||||
// clang looses it on this one, and generates a huge jump table when
|
||||
// inlined. So we don't mark it as inline (only constexpr) which solves the problem,
|
||||
// strangely, when not inlined, clang simply generates an array lookup.
|
||||
constexpr /* inline */ GLenum getInternalFormat(backend::TextureFormat format) noexcept {
|
||||
using TextureFormat = backend::TextureFormat;
|
||||
constexpr /* inline */ GLenum getInternalFormat(TextureFormat format) noexcept {
|
||||
using TextureFormat = TextureFormat;
|
||||
switch (format) {
|
||||
// 8-bits per element
|
||||
case TextureFormat::R8: return GL_R8;
|
||||
@@ -507,29 +504,14 @@ constexpr /* inline */ GLenum getInternalFormat(backend::TextureFormat format) n
|
||||
}
|
||||
}
|
||||
|
||||
class unordered_string_set : public std::unordered_set<std::string> {
|
||||
class unordered_string_set : public std::unordered_set<std::string_view> {
|
||||
public:
|
||||
bool has(const char* str) {
|
||||
return find(std::string(str)) != end();
|
||||
}
|
||||
bool has(std::string_view str) const noexcept;
|
||||
};
|
||||
|
||||
inline unordered_string_set split(const char* spacedList) {
|
||||
unordered_string_set set;
|
||||
const char* current = spacedList;
|
||||
const char* head = current;
|
||||
do {
|
||||
head = strchr(current, ' ');
|
||||
std::string s(current, head ? head - current : strlen(current));
|
||||
if (s.length()) {
|
||||
set.insert(std::move(s));
|
||||
}
|
||||
current = head + 1;
|
||||
} while (head);
|
||||
return set;
|
||||
}
|
||||
unordered_string_set split(const char* extensions) noexcept;
|
||||
|
||||
} // namespace GLUtils
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_GLUTILS_H
|
||||
#endif // TNT_FILAMENT_BACKEND_OPENGL_GLUTILS_H
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_NULLGLES_H
|
||||
#define TNT_FILAMENT_DRIVER_NULLGLES_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_NULLGLES_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_NULLGLES_H
|
||||
|
||||
/*
|
||||
* This is used for debugging (stubbing out GLES calls)
|
||||
@@ -27,7 +27,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
namespace nullgles {
|
||||
|
||||
inline void glScissor(GLint, GLint, GLsizei, GLsizei) { }
|
||||
@@ -81,6 +81,6 @@ inline GLenum glGetError() { return GL_NO_ERROR; }
|
||||
// turn GLES calls defined above into no-ops
|
||||
//using namespace nullgles;
|
||||
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_NULLGLES_H
|
||||
#endif // TNT_FILAMENT_BACKEND_OPENGL_NULLGLES_H
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "OpenGLBlitter.h"
|
||||
|
||||
#include "GLUtils.h"
|
||||
#include "OpenGLContext.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
|
||||
using namespace filament::math;
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
|
||||
static const char s_vertexES[] = R"SHADER(#version 300 es
|
||||
in vec4 pos;
|
||||
void main() {
|
||||
gl_Position = pos;
|
||||
}
|
||||
)SHADER";
|
||||
|
||||
static const char s_vertexGL[] = R"SHADER(#version 410 core
|
||||
in vec4 pos;
|
||||
void main() {
|
||||
gl_Position = pos;
|
||||
}
|
||||
)SHADER";
|
||||
|
||||
static const char s_fragmentES[] = R"SHADER(#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
precision mediump float;
|
||||
uniform samplerExternalOES sampler;
|
||||
out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = texelFetch(sampler, ivec2(gl_FragCoord.xy), 0);
|
||||
}
|
||||
)SHADER";
|
||||
|
||||
static const char s_fragmentGL[] = R"SHADER(#version 410 core
|
||||
precision mediump float;
|
||||
uniform sampler2D sampler;
|
||||
out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = texelFetch(sampler, ivec2(gl_FragCoord.xy), 0);
|
||||
}
|
||||
)SHADER";
|
||||
|
||||
void OpenGLBlitter::init() noexcept {
|
||||
glGenSamplers(1, &mSampler);
|
||||
glSamplerParameteri(mSampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(mSampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(mSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(mSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(mSampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
GLint status;
|
||||
char const* vsource[2] = { s_vertexES, s_vertexGL };
|
||||
char const* fsource[2] = { s_fragmentES, s_fragmentGL };
|
||||
const size_t index = GLES30_HEADERS ? 0 : 1;
|
||||
|
||||
mVertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(mVertexShader, 1, vsource + index, nullptr);
|
||||
glCompileShader(mVertexShader);
|
||||
glGetShaderiv(mVertexShader, GL_COMPILE_STATUS, &status);
|
||||
assert_invariant(status == GL_TRUE);
|
||||
|
||||
mFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(mFragmentShader, 1, fsource + index, nullptr);
|
||||
glCompileShader(mFragmentShader);
|
||||
glGetShaderiv(mFragmentShader, GL_COMPILE_STATUS, &status);
|
||||
assert_invariant(status == GL_TRUE);
|
||||
|
||||
mProgram = glCreateProgram();
|
||||
glAttachShader(mProgram, mVertexShader);
|
||||
glAttachShader(mProgram, mFragmentShader);
|
||||
glLinkProgram(mProgram);
|
||||
glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
|
||||
assert_invariant(status == GL_TRUE);
|
||||
|
||||
glUseProgram(mProgram);
|
||||
GLint loc = glGetUniformLocation(mProgram, "sampler");
|
||||
GLuint tmu = 0;
|
||||
glUniform1i(loc, tmu);
|
||||
|
||||
glGenFramebuffers(1, &mFBO);
|
||||
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLBlitter::terminate() noexcept {
|
||||
glDeleteSamplers(1, &mSampler);
|
||||
glDetachShader(mProgram, mVertexShader);
|
||||
glDetachShader(mProgram, mFragmentShader);
|
||||
glDeleteShader(mVertexShader);
|
||||
glDeleteShader(mFragmentShader);
|
||||
glDeleteProgram(mProgram);
|
||||
glDeleteFramebuffers(1, &mFBO);
|
||||
}
|
||||
|
||||
void OpenGLBlitter::blit(GLuint srcTextureExternal, GLuint dstTexture2d, GLuint w, GLuint h) noexcept {
|
||||
const float2 vtx[3] = {{ -1.0f, 3.0f },
|
||||
{ -1.0f, -1.0f },
|
||||
{ 3.0f, -1.0f }};
|
||||
|
||||
// we're using tmu 0 as the source texture
|
||||
GLuint tmu = 0;
|
||||
|
||||
// source texture
|
||||
glBindSampler(tmu, mSampler);
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, srcTextureExternal);
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
|
||||
// destination texture
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTexture2d, 0);
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_FRAMEBUFFER)
|
||||
|
||||
// geometry
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vtx);
|
||||
|
||||
// blit...
|
||||
glViewport(0, 0, w, h);
|
||||
glUseProgram(mProgram);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLBlitter::State::save() noexcept {
|
||||
mHasState = true;
|
||||
// TODO: technically we should also save glVertexAttribPointer
|
||||
GLuint tmu = 0;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &framebuffer);
|
||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &array);
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
glGetIntegerv(GL_COLOR_WRITEMASK, writeMask);
|
||||
scissorTest = glIsEnabled(GL_SCISSOR_TEST);
|
||||
stencilTest = glIsEnabled(GL_STENCIL_TEST);
|
||||
cullFace = glIsEnabled(GL_CULL_FACE);
|
||||
glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vertexAttrib);
|
||||
|
||||
// save the current active texture first
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
|
||||
|
||||
// we're using tmu 0 as the source texture
|
||||
glActiveTexture(GL_TEXTURE0 + tmu);
|
||||
|
||||
// save what depends on glActiveTexture
|
||||
glGetIntegerv(GL_SAMPLER_BINDING, &sampler);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
|
||||
|
||||
/*
|
||||
* Set the state
|
||||
*/
|
||||
|
||||
// we're using tmu 0 as the source texture
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLBlitter::State::restore() noexcept {
|
||||
GLuint tmu = 0;
|
||||
glColorMask(
|
||||
(GLboolean)writeMask[0],
|
||||
(GLboolean)writeMask[1],
|
||||
(GLboolean)writeMask[2],
|
||||
(GLboolean)writeMask[3]);
|
||||
if (cullFace) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
if (stencilTest) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
}
|
||||
if (scissorTest) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
glUseProgram(static_cast<GLuint>(program));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, static_cast<GLuint>(array));
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(framebuffer));
|
||||
if (!vertexAttrib) {
|
||||
glDisableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(texture));
|
||||
glBindSampler(tmu, static_cast<GLuint>(sampler));
|
||||
glActiveTexture(static_cast<GLenum>(activeTexture));
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_DRIVER_OPENGLBLITTER_H
|
||||
#define TNT_FILAMENT_DRIVER_OPENGLBLITTER_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include "gl_headers.h"
|
||||
|
||||
namespace filament {
|
||||
|
||||
class OpenGLContext;
|
||||
|
||||
class OpenGLBlitter {
|
||||
public:
|
||||
explicit OpenGLBlitter(OpenGLContext& context) noexcept : mContext(context) {}
|
||||
|
||||
void init() noexcept;
|
||||
void terminate() noexcept;
|
||||
|
||||
void blit(GLuint srcTextureExternal, GLuint dstTexture2d, GLuint w, GLuint h) noexcept;
|
||||
|
||||
class State {
|
||||
bool mHasState = false;
|
||||
GLint activeTexture, sampler, texture, framebuffer, array, vertexAttrib, program;
|
||||
GLboolean stencilTest, scissorTest, cullFace;
|
||||
GLint viewport[4], writeMask[4];
|
||||
void save() noexcept;
|
||||
void restore() noexcept;
|
||||
public:
|
||||
void setup() noexcept {
|
||||
if (UTILS_UNLIKELY(!mHasState)) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
~State() noexcept {
|
||||
if (UTILS_UNLIKELY(mHasState)) {
|
||||
restore();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
UTILS_UNUSED OpenGLContext& mContext;
|
||||
GLuint mSampler{};
|
||||
GLuint mVertexShader{};
|
||||
GLuint mFragmentShader{};
|
||||
GLuint mProgram{};
|
||||
GLuint mFBO{};
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_OPENGLBLITTER_H
|
||||
@@ -19,122 +19,153 @@
|
||||
// change to true to display all GL extensions in the console on start-up
|
||||
#define DEBUG_PRINT_EXTENSIONS false
|
||||
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
using namespace backend;
|
||||
bool OpenGLContext::queryOpenGLVersion(GLint* major, GLint* minor) noexcept {
|
||||
if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GLES) {
|
||||
char const* version = (char const*)glGetString(GL_VERSION);
|
||||
// This works on all versions of GLES
|
||||
int n = version ? sscanf(version, "OpenGL ES %d.%d", major, minor) : 0;
|
||||
return n == 2;
|
||||
} else if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL) {
|
||||
// OpenGL version
|
||||
glGetIntegerv(GL_MAJOR_VERSION, major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, minor);
|
||||
return (glGetError() == GL_NO_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLContext::OpenGLContext() noexcept {
|
||||
state.vao.p = &mDefaultVAO;
|
||||
state.enables.caps.set(getIndexForCap(GL_DITHER));
|
||||
|
||||
UTILS_UNUSED char const* const vendor = (char const*) glGetString(GL_VENDOR);
|
||||
UTILS_UNUSED char const* const renderer = (char const*) glGetString(GL_RENDERER);
|
||||
UTILS_UNUSED char const* const version = (char const*) glGetString(GL_VERSION);
|
||||
UTILS_UNUSED char const* const shader = (char const*) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
// There query work with all GL/GLES versions!
|
||||
state.vendor = (char const*)glGetString(GL_VENDOR);
|
||||
state.renderer = (char const*)glGetString(GL_RENDERER);
|
||||
state.version = (char const*)glGetString(GL_VERSION);
|
||||
state.shader = (char const*)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
|
||||
slog.v << "[" << vendor << "], [" << renderer << "], [" << version << "], [" << shader << "]" << io::endl;
|
||||
slog.v << "[" << state.vendor << "], [" << state.renderer << "], "
|
||||
"[" << state.version << "], [" << state.shader << "]" << io::endl;
|
||||
|
||||
// OpenGL (ES) version
|
||||
GLint major = 0;
|
||||
GLint minor = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
/*
|
||||
* Figure out GL / GLES version and available features
|
||||
*/
|
||||
|
||||
// Figure out if we have the extension we need
|
||||
GLint n = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
|
||||
ExtentionSet exts;
|
||||
for (GLint i = 0; i < n; i++) {
|
||||
const char * const extension = (const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i);
|
||||
exts.insert(StaticString::make(extension, strlen(extension)));
|
||||
if (DEBUG_PRINT_EXTENSIONS) {
|
||||
slog.d << extension << io::endl;
|
||||
queryOpenGLVersion(&state.major, &state.minor);
|
||||
|
||||
if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GLES) {
|
||||
// This works on all versions of GLES
|
||||
if (state.major == 3 && state.minor >= 0) {
|
||||
mShaderModel = ShaderModel::GL_ES_30;
|
||||
}
|
||||
}
|
||||
ShaderModel shaderModel = ShaderModel::UNKNOWN;
|
||||
if (GLES30_HEADERS) {
|
||||
if (major == 3 && minor >= 0) {
|
||||
shaderModel = ShaderModel::GL_ES_30;
|
||||
}
|
||||
if (major == 3 && minor >= 1) {
|
||||
if (state.major == 3 && state.minor >= 1) {
|
||||
features.multisample_texture = true;
|
||||
}
|
||||
initExtensionsGLES(major, minor, exts);
|
||||
} else if (GL41_HEADERS) {
|
||||
if (major == 4 && minor >= 1) {
|
||||
shaderModel = ShaderModel::GL_CORE_41;
|
||||
initExtensionsGLES();
|
||||
} else if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL) {
|
||||
// OpenGL version
|
||||
if (state.major == 4 && state.minor >= 1) {
|
||||
mShaderModel = ShaderModel::GL_CORE_41;
|
||||
}
|
||||
initExtensionsGL(major, minor, exts);
|
||||
features.multisample_texture = true;
|
||||
// feedback loops are allowed on GL desktop as long as writes are disabled
|
||||
bugs.allow_read_only_ancillary_feedback_loop = true;
|
||||
initExtensionsGL();
|
||||
}
|
||||
assert_invariant(shaderModel != ShaderModel::UNKNOWN);
|
||||
mShaderModel = shaderModel;
|
||||
|
||||
// Figure out which driver bugs we need to workaround
|
||||
if (strstr(renderer, "Adreno")) {
|
||||
bugs.invalidate_end_only_if_invalidate_start = true;
|
||||
assert_invariant(mShaderModel != ShaderModel::UNKNOWN);
|
||||
|
||||
// On Adreno (As of 3/20) timer query seem to return the CPU time, not the GPU time.
|
||||
bugs.dont_use_timer_query = true;
|
||||
/*
|
||||
* Figure out which driver bugs we need to workaround
|
||||
*/
|
||||
|
||||
// Blits to texture arrays are failing
|
||||
// This bug continues to reproduce, though at times we've seen it appear to "go away". The
|
||||
// standalone sample app that was written to show this problem still reproduces.
|
||||
// The working hypthesis is that some other state affects this behavior.
|
||||
bugs.disable_sidecar_blit_into_texture_array = true;
|
||||
const bool isAngle = strstr(state.renderer, "ANGLE");
|
||||
if (!isAngle) {
|
||||
if (strstr(state.renderer, "Adreno")) {
|
||||
// Qualcomm GPU
|
||||
bugs.invalidate_end_only_if_invalidate_start = true;
|
||||
|
||||
// early exit condition is flattened in EASU code
|
||||
bugs.split_easu = true;
|
||||
|
||||
int maj, min, driverMajor, driverMinor;
|
||||
int c = sscanf(version, "OpenGL ES %d.%d V@%d.%d", // NOLINT(cert-err34-c)
|
||||
&maj, &min, &driverMajor, &driverMinor);
|
||||
if (c == 4) {
|
||||
// workarounds based on version here.
|
||||
// notes:
|
||||
// bugs.invalidate_end_only_if_invalidate_start
|
||||
// - appeared at least in "OpenGL ES 3.2 V@0490.0 (GIT@85da404, I46ff5fc46f, 1606794520) (Date:11/30/20)"
|
||||
// - wasn't present in "OpenGL ES 3.2 V@0490.0 (GIT@0905e9f, Ia11ce2d146, 1599072951) (Date:09/02/20)"
|
||||
// - has been confirmed fixed in V@570.1 by Qualcomm
|
||||
if (driverMajor < 490 || driverMajor > 570 || (driverMajor == 570 && driverMinor >= 1)) {
|
||||
bugs.invalidate_end_only_if_invalidate_start = false;
|
||||
}
|
||||
}
|
||||
|
||||
// qualcomm seems to have no problem with this (which is good for us)
|
||||
bugs.allow_read_only_ancillary_feedback_loop = true;
|
||||
} else if (strstr(renderer, "Mali")) {
|
||||
bugs.vao_doesnt_store_element_array_buffer_binding = true;
|
||||
if (strstr(renderer, "Mali-T")) {
|
||||
bugs.disable_glFlush = true;
|
||||
bugs.disable_shared_context_draws = true;
|
||||
bugs.texture_external_needs_rebind = true;
|
||||
// We have not verified that timer queries work on Mali-T, so we disable to be safe.
|
||||
// On Adreno (As of 3/20) timer query seem to return the CPU time, not the GPU time.
|
||||
bugs.dont_use_timer_query = true;
|
||||
}
|
||||
if (strstr(renderer, "Mali-G")) {
|
||||
// note: We have verified that timer queries work well at least on some Mali-G.
|
||||
}
|
||||
|
||||
// Mali seems to have no problem with this (which is good for us)
|
||||
bugs.allow_read_only_ancillary_feedback_loop = true;
|
||||
} else if (strstr(renderer, "Intel")) {
|
||||
bugs.vao_doesnt_store_element_array_buffer_binding = true;
|
||||
} else if (strstr(renderer, "PowerVR")) {
|
||||
} else if (strstr(renderer, "Apple")) {
|
||||
} else if (strstr(renderer, "Tegra") || strstr(renderer, "GeForce") || strstr(renderer, "NV")) {
|
||||
} else if (strstr(renderer, "Vivante")) {
|
||||
} else if (strstr(renderer, "AMD") || strstr(renderer, "ATI")) {
|
||||
} else if (strstr(renderer, "Mozilla")) {
|
||||
bugs.disable_invalidate_framebuffer = true;
|
||||
// Blits to texture arrays are failing
|
||||
// This bug continues to reproduce, though at times we've seen it appear to "go away".
|
||||
// The standalone sample app that was written to show this problem still reproduces.
|
||||
// The working hypthesis is that some other state affects this behavior.
|
||||
bugs.disable_sidecar_blit_into_texture_array = true;
|
||||
|
||||
// early exit condition is flattened in EASU code
|
||||
bugs.split_easu = true;
|
||||
|
||||
int maj, min, driverMajor, driverMinor;
|
||||
int c = sscanf(state.version, "OpenGL ES %d.%d V@%d.%d", // NOLINT(cert-err34-c)
|
||||
&maj, &min, &driverMajor, &driverMinor);
|
||||
if (c == 4) {
|
||||
// workarounds based on version here.
|
||||
// notes:
|
||||
// bugs.invalidate_end_only_if_invalidate_start
|
||||
// - appeared at least in
|
||||
// "OpenGL ES 3.2 V@0490.0 (GIT@85da404, I46ff5fc46f, 1606794520) (Date:11/30/20)"
|
||||
// - wasn't present in
|
||||
// "OpenGL ES 3.2 V@0490.0 (GIT@0905e9f, Ia11ce2d146, 1599072951) (Date:09/02/20)"
|
||||
// - has been confirmed fixed in V@570.1 by Qualcomm
|
||||
if (driverMajor < 490 || driverMajor > 570 ||
|
||||
(driverMajor == 570 && driverMinor >= 1)) {
|
||||
bugs.invalidate_end_only_if_invalidate_start = false;
|
||||
}
|
||||
}
|
||||
|
||||
// qualcomm seems to have no problem with this (which is good for us)
|
||||
bugs.allow_read_only_ancillary_feedback_loop = true;
|
||||
} else if (strstr(state.renderer, "Mali")) {
|
||||
// ARM GPU
|
||||
bugs.vao_doesnt_store_element_array_buffer_binding = true;
|
||||
if (strstr(state.renderer, "Mali-T")) {
|
||||
bugs.disable_glFlush = true;
|
||||
bugs.disable_shared_context_draws = true;
|
||||
bugs.texture_external_needs_rebind = true;
|
||||
// We have not verified that timer queries work on Mali-T, so we disable to be safe.
|
||||
bugs.dont_use_timer_query = true;
|
||||
}
|
||||
if (strstr(state.renderer, "Mali-G")) {
|
||||
// note: We have verified that timer queries work well at least on some Mali-G.
|
||||
}
|
||||
// Mali seems to have no problem with this (which is good for us)
|
||||
bugs.allow_read_only_ancillary_feedback_loop = true;
|
||||
} else if (strstr(state.renderer, "Intel")) {
|
||||
// Intel GPU
|
||||
bugs.vao_doesnt_store_element_array_buffer_binding = true;
|
||||
} else if (strstr(state.renderer, "PowerVR")) {
|
||||
// PowerVR GPU
|
||||
} else if (strstr(state.renderer, "Apple")) {
|
||||
// Apple GPU
|
||||
} else if (strstr(state.renderer, "Tegra") ||
|
||||
strstr(state.renderer, "GeForce") ||
|
||||
strstr(state.renderer, "NV")) {
|
||||
// NVIDIA GPU
|
||||
} else if (strstr(state.renderer, "Vivante")) {
|
||||
// Vivante GPU
|
||||
} else if (strstr(state.renderer, "AMD") ||
|
||||
strstr(state.renderer, "ATI")) {
|
||||
// AMD/ATI GPU
|
||||
} else if (strstr(state.renderer, "Mozilla")) {
|
||||
bugs.disable_invalidate_framebuffer = true;
|
||||
}
|
||||
} else {
|
||||
// When running under ANGLE, it's a different set of workaround that we need.
|
||||
if (strstr(state.renderer, "Adreno")) {
|
||||
// Qualcomm GPU
|
||||
// early exit condition is flattened in EASU code
|
||||
// (that should be regardless of ANGLE, but we should double check)
|
||||
bugs.split_easu = true;
|
||||
}
|
||||
// TODO: see if we could use `bugs.allow_read_only_ancillary_feedback_loop = true`
|
||||
}
|
||||
|
||||
slog.v << "Active workarounds: " << '\n';
|
||||
UTILS_NOUNROLL
|
||||
for (auto [enabled, name, _] : mBugDatabase) {
|
||||
if (enabled) {
|
||||
slog.v << name << '\n';
|
||||
@@ -186,7 +217,7 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
|
||||
// Point sprite size and seamless cubemap filtering are disabled by default in desktop GL.
|
||||
// In OpenGL ES, these flags do not exist because they are always on.
|
||||
#if GL41_HEADERS
|
||||
#if BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL
|
||||
enable(GL_PROGRAM_POINT_SIZE);
|
||||
#endif
|
||||
|
||||
@@ -219,50 +250,27 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
if (ext.KHR_debug) {
|
||||
auto cb = [](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
|
||||
const GLchar* message, const void *userParam) {
|
||||
io::ostream* stream = nullptr;
|
||||
io::ostream* stream = &slog.i;
|
||||
switch (severity) {
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
stream = &slog.e;
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
stream = &slog.w;
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
stream = &slog.d;
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_HIGH: stream = &slog.e; break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM: stream = &slog.w; break;
|
||||
case GL_DEBUG_SEVERITY_LOW: stream = &slog.d; break;
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||
default:
|
||||
stream = &slog.i;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
io::ostream& out = *stream;
|
||||
out << "KHR_debug ";
|
||||
const char* level = ": ";
|
||||
switch (type) {
|
||||
case GL_DEBUG_TYPE_ERROR:
|
||||
out << "ERROR";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
out << "DEPRECATED_BEHAVIOR";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
out << "UNDEFINED_BEHAVIOR";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PORTABILITY:
|
||||
out << "PORTABILITY";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PERFORMANCE:
|
||||
out << "PERFORMANCE";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_OTHER:
|
||||
out << "OTHER";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_MARKER:
|
||||
out << "MARKER";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case GL_DEBUG_TYPE_ERROR: level = "ERROR: "; break;
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: level = "DEPRECATED_BEHAVIOR: "; break;
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: level = "UNDEFINED_BEHAVIOR: "; break;
|
||||
case GL_DEBUG_TYPE_PORTABILITY: level = "PORTABILITY: "; break;
|
||||
case GL_DEBUG_TYPE_PERFORMANCE: level = "PERFORMANCE: "; break;
|
||||
case GL_DEBUG_TYPE_OTHER: level = "OTHER: "; break;
|
||||
case GL_DEBUG_TYPE_MARKER: level = "MARKER: "; break;
|
||||
default: break;
|
||||
}
|
||||
out << ": " << message << io::endl;
|
||||
out << "KHR_debug " << level << message << io::endl;
|
||||
};
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
@@ -277,60 +285,81 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
bool OpenGLContext::hasExtension(ExtentionSet const& map, utils::StaticString ext) noexcept {
|
||||
return map.find(ext) != map.end();
|
||||
}
|
||||
void OpenGLContext::initExtensionsGLES() noexcept {
|
||||
const char * const extensions = (const char*)glGetString(GL_EXTENSIONS);
|
||||
GLUtils::unordered_string_set exts = GLUtils::split(extensions);
|
||||
if constexpr (DEBUG_PRINT_EXTENSIONS) {
|
||||
for (auto extension: exts) {
|
||||
slog.d << "\"" << std::string_view(extension) << "\"\n";
|
||||
}
|
||||
flush(slog.d);
|
||||
}
|
||||
|
||||
void OpenGLContext::initExtensionsGLES(GLint major, GLint minor, ExtentionSet const& exts) {
|
||||
// figure out and initialize the extensions we need
|
||||
ext.APPLE_color_buffer_packed_float = hasExtension(exts, "GL_APPLE_color_buffer_packed_float");
|
||||
ext.EXT_clip_control = hasExtension(exts, "GL_EXT_clip_control");
|
||||
ext.EXT_color_buffer_float = hasExtension(exts, "GL_EXT_color_buffer_float");
|
||||
ext.EXT_color_buffer_half_float = hasExtension(exts, "GL_EXT_color_buffer_half_float");
|
||||
ext.EXT_debug_marker = hasExtension(exts, "GL_EXT_debug_marker");
|
||||
ext.EXT_disjoint_timer_query = hasExtension(exts, "GL_EXT_disjoint_timer_query");
|
||||
ext.EXT_multisampled_render_to_texture = hasExtension(exts, "GL_EXT_multisampled_render_to_texture");
|
||||
ext.EXT_multisampled_render_to_texture2 = hasExtension(exts, "GL_EXT_multisampled_render_to_texture2");
|
||||
ext.EXT_shader_framebuffer_fetch = hasExtension(exts, "GL_EXT_shader_framebuffer_fetch");
|
||||
using namespace std::literals;
|
||||
ext.APPLE_color_buffer_packed_float = exts.has("GL_APPLE_color_buffer_packed_float"sv);
|
||||
ext.EXT_clip_control = exts.has("GL_EXT_clip_control"sv);
|
||||
ext.EXT_color_buffer_float = exts.has("GL_EXT_color_buffer_float"sv);
|
||||
ext.EXT_color_buffer_half_float = exts.has("GL_EXT_color_buffer_half_float"sv);
|
||||
ext.EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
ext.EXT_disjoint_timer_query = exts.has("GL_EXT_disjoint_timer_query"sv);
|
||||
ext.EXT_multisampled_render_to_texture = exts.has("GL_EXT_multisampled_render_to_texture"sv);
|
||||
ext.EXT_multisampled_render_to_texture2 = exts.has("GL_EXT_multisampled_render_to_texture2"sv);
|
||||
ext.EXT_shader_framebuffer_fetch = exts.has("GL_EXT_shader_framebuffer_fetch"sv);
|
||||
ext.EXT_texture_compression_etc2 = true;
|
||||
ext.EXT_texture_filter_anisotropic = hasExtension(exts, "GL_EXT_texture_filter_anisotropic");
|
||||
ext.GOOGLE_cpp_style_line_directive = hasExtension(exts, "GL_GOOGLE_cpp_style_line_directive");
|
||||
ext.KHR_debug = hasExtension(exts, "GL_KHR_debug");
|
||||
ext.OES_EGL_image_external_essl3 = hasExtension(exts, "GL_OES_EGL_image_external_essl3");
|
||||
ext.QCOM_tiled_rendering = hasExtension(exts, "GL_QCOM_tiled_rendering");
|
||||
ext.EXT_texture_compression_s3tc = hasExtension(exts, "GL_EXT_texture_compression_s3tc");
|
||||
ext.EXT_texture_compression_s3tc_srgb = hasExtension(exts, "GL_EXT_texture_compression_s3tc_srgb");
|
||||
ext.WEBGL_compressed_texture_s3tc = hasExtension(exts, "WEBGL_compressed_texture_s3tc");
|
||||
ext.WEBGL_compressed_texture_s3tc_srgb = hasExtension(exts, "WEBGL_compressed_texture_s3tc_srgb");
|
||||
ext.WEBGL_compressed_texture_etc = hasExtension(exts, "WEBGL_compressed_texture_etc");
|
||||
ext.EXT_texture_filter_anisotropic = exts.has("GL_EXT_texture_filter_anisotropic"sv);
|
||||
ext.GOOGLE_cpp_style_line_directive = exts.has("GL_GOOGLE_cpp_style_line_directive"sv);
|
||||
ext.KHR_debug = exts.has("GL_KHR_debug"sv);
|
||||
ext.OES_EGL_image_external_essl3 = exts.has("GL_OES_EGL_image_external_essl3"sv);
|
||||
ext.QCOM_tiled_rendering = exts.has("GL_QCOM_tiled_rendering"sv);
|
||||
ext.EXT_texture_compression_s3tc = exts.has("GL_EXT_texture_compression_s3tc"sv);
|
||||
ext.EXT_texture_compression_s3tc_srgb = exts.has("GL_EXT_texture_compression_s3tc_srgb"sv);
|
||||
ext.WEBGL_compressed_texture_s3tc = exts.has("WEBGL_compressed_texture_s3tc"sv);
|
||||
ext.WEBGL_compressed_texture_s3tc_srgb = exts.has("WEBGL_compressed_texture_s3tc_srgb"sv);
|
||||
ext.WEBGL_compressed_texture_etc = exts.has("WEBGL_compressed_texture_etc"sv);
|
||||
// ES 3.2 implies EXT_color_buffer_float
|
||||
if (major >= 3 && minor >= 2) {
|
||||
if (state.major >= 3 && state.minor >= 2) {
|
||||
ext.EXT_color_buffer_float = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLContext::initExtensionsGL(GLint major, GLint minor, ExtentionSet const& exts) {
|
||||
void OpenGLContext::initExtensionsGL() noexcept {
|
||||
GLUtils::unordered_string_set exts;
|
||||
GLint n = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
|
||||
for (GLint i = 0; i < n; i++) {
|
||||
exts.emplace((const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i));
|
||||
}
|
||||
if constexpr (DEBUG_PRINT_EXTENSIONS) {
|
||||
for (auto extension: exts) {
|
||||
slog.d << "\"" << std::string_view(extension) << "\"\n";
|
||||
}
|
||||
flush(slog.d);
|
||||
}
|
||||
|
||||
using namespace std::literals;
|
||||
auto major = state.major;
|
||||
auto minor = state.minor;
|
||||
ext.APPLE_color_buffer_packed_float = true; // Assumes core profile.
|
||||
ext.ARB_shading_language_packing = hasExtension(exts, "GL_ARB_shading_language_packing") || (major == 4 && minor >= 2);
|
||||
ext.EXT_clip_control = hasExtension(exts, "GL_ARB_clip_control") || (major == 4 && minor >= 5);
|
||||
ext.ARB_shading_language_packing = exts.has("GL_ARB_shading_language_packing"sv) || (major == 4 && minor >= 2);
|
||||
ext.EXT_clip_control = exts.has("GL_ARB_clip_control"sv) || (major == 4 && minor >= 5);
|
||||
ext.EXT_color_buffer_float = true; // Assumes core profile.
|
||||
ext.EXT_color_buffer_half_float = true; // Assumes core profile.
|
||||
ext.EXT_debug_marker = hasExtension(exts, "GL_EXT_debug_marker");
|
||||
ext.EXT_shader_framebuffer_fetch = hasExtension(exts, "GL_EXT_shader_framebuffer_fetch");
|
||||
ext.EXT_texture_compression_etc2 = hasExtension(exts, "GL_ARB_ES3_compatibility");
|
||||
ext.EXT_texture_filter_anisotropic = hasExtension(exts, "GL_EXT_texture_filter_anisotropic");
|
||||
ext.EXT_texture_sRGB = hasExtension(exts, "GL_EXT_texture_sRGB");
|
||||
ext.GOOGLE_cpp_style_line_directive = hasExtension(exts, "GL_GOOGLE_cpp_style_line_directive");
|
||||
ext.EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
ext.EXT_shader_framebuffer_fetch = exts.has("GL_EXT_shader_framebuffer_fetch"sv);
|
||||
ext.EXT_texture_compression_etc2 = exts.has("GL_ARB_ES3_compatibility"sv);
|
||||
ext.EXT_texture_filter_anisotropic = exts.has("GL_EXT_texture_filter_anisotropic"sv);
|
||||
ext.EXT_texture_sRGB = exts.has("GL_EXT_texture_sRGB"sv);
|
||||
ext.GOOGLE_cpp_style_line_directive = exts.has("GL_GOOGLE_cpp_style_line_directive"sv);
|
||||
ext.KHR_debug = major >= 4 && minor >= 3;
|
||||
ext.OES_EGL_image_external_essl3 = hasExtension(exts, "GL_OES_EGL_image_external_essl3");
|
||||
ext.EXT_texture_compression_s3tc = hasExtension(exts, "GL_EXT_texture_compression_s3tc");
|
||||
ext.EXT_texture_compression_s3tc_srgb = hasExtension(exts, "GL_EXT_texture_compression_s3tc_srgb");
|
||||
ext.OES_EGL_image_external_essl3 = exts.has("GL_OES_EGL_image_external_essl3"sv);
|
||||
ext.EXT_texture_compression_s3tc = exts.has("GL_EXT_texture_compression_s3tc"sv);
|
||||
ext.EXT_texture_compression_s3tc_srgb = exts.has("GL_EXT_texture_compression_s3tc_srgb"sv);
|
||||
}
|
||||
|
||||
void OpenGLContext::bindBuffer(GLenum target, GLuint buffer) noexcept {
|
||||
size_t targetIndex = getIndexForBufferTarget(target);
|
||||
if (target == GL_ELEMENT_ARRAY_BUFFER) {
|
||||
constexpr size_t targetIndex = getIndexForBufferTarget(GL_ELEMENT_ARRAY_BUFFER);
|
||||
// GL_ELEMENT_ARRAY_BUFFER is a special case, where the currently bound VAO remembers
|
||||
// the index buffer, unless there are no VAO bound (see: bindVertexArray)
|
||||
assert_invariant(state.vao.p);
|
||||
@@ -343,6 +372,7 @@ void OpenGLContext::bindBuffer(GLenum target, GLuint buffer) noexcept {
|
||||
glBindBuffer(target, buffer);
|
||||
}
|
||||
} else {
|
||||
size_t targetIndex = getIndexForBufferTarget(target);
|
||||
update_state(state.buffers.genericBinding[targetIndex], buffer, [&]() {
|
||||
glBindBuffer(target, buffer);
|
||||
});
|
||||
@@ -350,33 +380,22 @@ void OpenGLContext::bindBuffer(GLenum target, GLuint buffer) noexcept {
|
||||
}
|
||||
|
||||
void OpenGLContext::pixelStore(GLenum pname, GLint param) noexcept {
|
||||
GLint* pcur = nullptr;
|
||||
switch (pname) {
|
||||
case GL_PACK_ROW_LENGTH:
|
||||
pcur = &state.pack.row_length;
|
||||
break;
|
||||
case GL_PACK_SKIP_ROWS:
|
||||
pcur = &state.pack.skip_row;
|
||||
break;
|
||||
case GL_PACK_SKIP_PIXELS:
|
||||
pcur = &state.pack.skip_pixels;
|
||||
break;
|
||||
case GL_PACK_ALIGNMENT:
|
||||
pcur = &state.pack.alignment;
|
||||
break;
|
||||
GLint* pcur;
|
||||
|
||||
case GL_UNPACK_ROW_LENGTH:
|
||||
pcur = &state.unpack.row_length;
|
||||
break;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
pcur = &state.unpack.alignment;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_PIXELS:
|
||||
pcur = &state.unpack.skip_pixels;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_ROWS:
|
||||
pcur = &state.unpack.skip_row;
|
||||
break;
|
||||
// Note: GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS and
|
||||
// GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_ROWS
|
||||
// are actually provided as conveniences to the programmer; they provide no functionality
|
||||
// that cannot be duplicated at the call site (e.g. glTexImage2D or glReadPixels)
|
||||
|
||||
switch (pname) {
|
||||
case GL_PACK_ALIGNMENT: pcur = &state.pack.alignment; break;
|
||||
case GL_PACK_ROW_LENGTH: pcur = &state.pack.row_length; break;
|
||||
case GL_PACK_SKIP_PIXELS: pcur = &state.pack.skip_pixels; break; // convenience
|
||||
case GL_PACK_SKIP_ROWS: pcur = &state.pack.skip_row; break; // convenience
|
||||
case GL_UNPACK_ALIGNMENT: pcur = &state.unpack.alignment; break;
|
||||
case GL_UNPACK_ROW_LENGTH: pcur = &state.unpack.row_length; break;
|
||||
case GL_UNPACK_SKIP_PIXELS: pcur = &state.unpack.skip_pixels; break; // convenience
|
||||
case GL_UNPACK_SKIP_ROWS: pcur = &state.unpack.skip_row; break; // convenience
|
||||
default:
|
||||
goto default_case;
|
||||
}
|
||||
@@ -393,6 +412,7 @@ void OpenGLContext::unbindTexture(GLenum target, GLuint texture_id) noexcept {
|
||||
// no need unbind the texture from FBOs because we're not tracking that state (and there is
|
||||
// no need to).
|
||||
const size_t index = getIndexForTextureTarget(target);
|
||||
UTILS_NOUNROLL
|
||||
for (GLuint unit = 0; unit < MAX_TEXTURE_UNIT_COUNT; unit++) {
|
||||
if (state.textures.units[unit].targets[index].texture_id == texture_id) {
|
||||
bindTexture(unit, target, (GLuint)0, index);
|
||||
@@ -402,7 +422,7 @@ void OpenGLContext::unbindTexture(GLenum target, GLuint texture_id) noexcept {
|
||||
|
||||
void OpenGLContext::unbindSampler(GLuint sampler) noexcept {
|
||||
// unbind this sampler from all the units it might be bound to
|
||||
#pragma nounroll // clang generates >800B of code!!!
|
||||
UTILS_NOUNROLL // clang generates >800B of code!!!
|
||||
for (GLuint unit = 0; unit < MAX_TEXTURE_UNIT_COUNT; unit++) {
|
||||
if (state.textures.units[unit].sampler == sampler) {
|
||||
bindSampler(unit, 0);
|
||||
@@ -415,7 +435,7 @@ void OpenGLContext::deleteBuffers(GLsizei n, const GLuint* buffers, GLenum targe
|
||||
// bindings of bound buffers are reset to 0
|
||||
const size_t targetIndex = getIndexForBufferTarget(target);
|
||||
auto& genericBuffer = state.buffers.genericBinding[targetIndex];
|
||||
#pragma nounroll
|
||||
UTILS_NOUNROLL
|
||||
for (GLsizei i = 0; i < n; ++i) {
|
||||
if (genericBuffer == buffers[i]) {
|
||||
genericBuffer = 0;
|
||||
@@ -423,9 +443,9 @@ void OpenGLContext::deleteBuffers(GLsizei n, const GLuint* buffers, GLenum targe
|
||||
}
|
||||
if (target == GL_UNIFORM_BUFFER || target == GL_TRANSFORM_FEEDBACK_BUFFER) {
|
||||
auto& indexedBuffer = state.buffers.targets[targetIndex];
|
||||
#pragma nounroll // clang generates >1 KiB of code!!
|
||||
UTILS_NOUNROLL // clang generates >1 KiB of code!!
|
||||
for (GLsizei i = 0; i < n; ++i) {
|
||||
#pragma nounroll
|
||||
UTILS_NOUNROLL
|
||||
for (auto& buffer : indexedBuffer.buffers) {
|
||||
if (buffer.name == buffers[i]) {
|
||||
buffer.name = 0;
|
||||
|
||||
@@ -30,47 +30,46 @@
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
namespace filament {
|
||||
namespace filament::backend {
|
||||
|
||||
class OpenGLContext {
|
||||
public:
|
||||
static constexpr const size_t MAX_TEXTURE_UNIT_COUNT = backend::MAX_SAMPLER_COUNT;
|
||||
static constexpr const size_t MAX_TEXTURE_UNIT_COUNT = MAX_SAMPLER_COUNT;
|
||||
static constexpr const size_t MAX_BUFFER_BINDINGS = 32;
|
||||
typedef math::details::TVec4<GLint> vec4gli;
|
||||
typedef math::details::TVec2<GLclampf> vec2glf;
|
||||
|
||||
// TODO: the footprint of this structure can be reduced. We need only 1 bit for index type, 16
|
||||
// bits for vertexAttribArray. We can also use fewer bits for vertexBufferVersion, although
|
||||
// this will require a corollary update in OpenGLDriver::setVertexBufferObject().
|
||||
struct RenderPrimitive {
|
||||
GLuint vao = 0;
|
||||
GLenum indicesType = GL_UNSIGNED_INT;
|
||||
GLuint elementArray = 0;
|
||||
utils::bitset32 vertexAttribArray;
|
||||
static_assert(MAX_VERTEX_ATTRIBUTE_COUNT <= 16);
|
||||
|
||||
GLuint vao = 0; // 4
|
||||
GLuint elementArray = 0; // 4
|
||||
utils::bitset<uint16_t> vertexAttribArray; // 2
|
||||
|
||||
// If this version number does not match vertexBufferWithObjects->bufferObjectsVersion,
|
||||
// then the VAO needs to be updated.
|
||||
uint8_t vertexBufferVersion = 0; // 1
|
||||
uint8_t indicesSize = 0; // 1
|
||||
|
||||
// The optional 32-bit handle to a GLVertexBuffer is necessary only if the referenced
|
||||
// VertexBuffer supports buffer objects. If this is zero, then the VBO handles array is
|
||||
// immutable.
|
||||
backend::Handle<backend::HwVertexBuffer> vertexBufferWithObjects = {};
|
||||
Handle<HwVertexBuffer> vertexBufferWithObjects = {}; // 4
|
||||
|
||||
// If this version number does not match vertexBufferWithObjects->bufferObjectsVersion,
|
||||
// then the VAO needs to be updated.
|
||||
uint8_t vertexBufferVersion = 0;
|
||||
GLenum getIndicesType() const noexcept {
|
||||
return indicesSize == 4 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
|
||||
}
|
||||
} gl;
|
||||
|
||||
OpenGLContext() noexcept;
|
||||
static bool queryOpenGLVersion(GLint* major, GLint* minor) noexcept;
|
||||
|
||||
// this is chosen to minimize code size
|
||||
using ExtentionSet = std::set<utils::StaticString>;
|
||||
static bool hasExtension(ExtentionSet const& exts, utils::StaticString ext) noexcept;
|
||||
void initExtensionsGLES(GLint major, GLint minor, ExtentionSet const& extensionsMap);
|
||||
void initExtensionsGL(GLint major, GLint minor, ExtentionSet const& extensionsMap);
|
||||
OpenGLContext() noexcept;
|
||||
|
||||
constexpr static inline size_t getIndexForTextureTarget(GLuint target) noexcept;
|
||||
constexpr inline size_t getIndexForCap(GLenum cap) noexcept;
|
||||
constexpr static inline size_t getIndexForBufferTarget(GLenum target) noexcept;
|
||||
|
||||
backend::ShaderModel getShaderModel() const noexcept { return mShaderModel; }
|
||||
ShaderModel getShaderModel() const noexcept { return mShaderModel; }
|
||||
|
||||
|
||||
inline void useProgram(GLuint program) noexcept;
|
||||
@@ -105,7 +104,7 @@ public:
|
||||
inline void polygonOffset(GLfloat factor, GLfloat units) noexcept;
|
||||
inline void beginQuery(GLenum target, GLuint query) noexcept;
|
||||
inline void endQuery(GLenum target) noexcept;
|
||||
inline GLuint getQuery(GLenum target) noexcept;
|
||||
inline GLuint getQuery(GLenum target) const noexcept;
|
||||
|
||||
inline void setScissor(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept;
|
||||
inline void viewport(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept;
|
||||
@@ -205,6 +204,19 @@ public:
|
||||
bool allow_read_only_ancillary_feedback_loop = false;
|
||||
} bugs;
|
||||
|
||||
// state getters -- as needed.
|
||||
vec4gli const& getViewport() const { return state.window.viewport; }
|
||||
|
||||
// function to handle state changes we don't control
|
||||
void updateTexImage(GLenum target, GLuint id) noexcept {
|
||||
const size_t index = getIndexForTextureTarget(target);
|
||||
state.textures.units[state.textures.active].targets[index].texture_id = id;
|
||||
}
|
||||
void resetProgram() noexcept { state.program.use = 0; }
|
||||
|
||||
private:
|
||||
ShaderModel mShaderModel = ShaderModel::UNKNOWN;
|
||||
|
||||
const std::array<std::tuple<bool const&, char const*, char const*>, sizeof(bugs)> mBugDatabase{{
|
||||
{ bugs.disable_glFlush,
|
||||
"disable_glFlush",
|
||||
@@ -244,22 +256,16 @@ public:
|
||||
""},
|
||||
}};
|
||||
|
||||
// state getters -- as needed.
|
||||
GLuint getDrawFbo() const noexcept { return state.draw_fbo; }
|
||||
vec4gli const& getViewport() const { return state.window.viewport; }
|
||||
|
||||
// function to handle state changes we don't control
|
||||
void updateTexImage(GLenum target, GLuint id) noexcept {
|
||||
const size_t index = getIndexForTextureTarget(target);
|
||||
state.textures.units[state.textures.active].targets[index].texture_id = id;
|
||||
}
|
||||
void resetProgram() noexcept { state.program.use = 0; }
|
||||
|
||||
private:
|
||||
backend::ShaderModel mShaderModel;
|
||||
|
||||
// Try to keep the State structure sorted by data-access patterns
|
||||
struct State {
|
||||
GLint major = 0;
|
||||
GLint minor = 0;
|
||||
|
||||
char const* vendor = nullptr;
|
||||
char const* renderer = nullptr;
|
||||
char const* version = nullptr;
|
||||
char const* shader = nullptr;
|
||||
|
||||
GLuint draw_fbo = 0;
|
||||
GLuint read_fbo = 0;
|
||||
|
||||
@@ -345,6 +351,10 @@ private:
|
||||
|
||||
RenderPrimitive mDefaultVAO;
|
||||
|
||||
// this is chosen to minimize code size
|
||||
void initExtensionsGLES() noexcept;
|
||||
void initExtensionsGL() noexcept;
|
||||
|
||||
template <typename T, typename F>
|
||||
static inline void update_state(T& state, T const& expected, F functor, bool force = false) noexcept {
|
||||
if (UTILS_UNLIKELY(force || state != expected)) {
|
||||
@@ -390,7 +400,7 @@ constexpr size_t OpenGLContext::getIndexForCap(GLenum cap) noexcept { //NOLINT
|
||||
#ifdef GL_ARB_seamless_cube_map
|
||||
case GL_TEXTURE_CUBE_MAP_SEAMLESS: index = 11; break;
|
||||
#endif
|
||||
#if GL41_HEADERS
|
||||
#if BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL
|
||||
case GL_PROGRAM_POINT_SIZE: index = 12; break;
|
||||
#endif
|
||||
default: index = 13; break; // should never happen
|
||||
@@ -661,7 +671,7 @@ void OpenGLContext::endQuery(GLenum target) noexcept {
|
||||
glEndQuery(target);
|
||||
}
|
||||
|
||||
GLuint OpenGLContext::getQuery(GLenum target) noexcept {
|
||||
GLuint OpenGLContext::getQuery(GLenum target) const noexcept {
|
||||
switch (target) {
|
||||
case GL_TIME_ELAPSED:
|
||||
return state.queries.timer;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user