зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1607940 - IPC TexImage. r=lsalzman,nika,handyman
Differential Revision: https://phabricator.services.mozilla.com/D83291
This commit is contained in:
Родитель
db06b9e526
Коммит
f25a4cdbe8
|
@ -882,9 +882,10 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot(
|
|||
if (!child->SendGetFrontBufferSnapshot(&res)) {
|
||||
res = {};
|
||||
}
|
||||
if (!res.shmem) return nullptr;
|
||||
const auto& surfSize = res.surfSize;
|
||||
const auto& shmemBytes = ByteRange(*res.shmem);
|
||||
const webgl::RaiiShmem shmem{child, res.shmem};
|
||||
const auto& shmemBytes = shmem.ByteRange();
|
||||
if (!surfSize.x) return nullptr; // Zero means failure.
|
||||
|
||||
const auto stride = surfSize.x * 4;
|
||||
const auto byteSize = stride * surfSize.y;
|
||||
|
@ -1158,6 +1159,11 @@ already_AddRefed<WebGLSyncJS> ClientWebGLContext::FenceSync(
|
|||
|
||||
auto ret = AsRefPtr(new WebGLSyncJS(*this));
|
||||
Run<RPROC(CreateSync)>(ret->mId);
|
||||
|
||||
auto& availRunnable = EnsureAvailabilityRunnable();
|
||||
availRunnable.mSyncs.push_back(ret.get());
|
||||
ret->mCanBeAvailable = false;
|
||||
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
|
@ -1620,7 +1626,7 @@ void ClientWebGLContext::GetInternalformatParameter(
|
|||
if (IsContextLost()) return;
|
||||
|
||||
const auto& inProcessContext = notLost->inProcess;
|
||||
Maybe<std::vector<int>> maybe;
|
||||
Maybe<std::vector<int32_t>> maybe;
|
||||
if (inProcessContext) {
|
||||
maybe = inProcessContext->GetInternalformatParameter(target, internalformat,
|
||||
pname);
|
||||
|
@ -1805,6 +1811,20 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
|||
case LOCAL_GL_PACK_ALIGNMENT:
|
||||
retval.set(JS::NumberValue(state.mPixelPackState.alignment));
|
||||
return;
|
||||
case LOCAL_GL_UNPACK_ALIGNMENT:
|
||||
retval.set(JS::NumberValue(state.mPixelUnpackState.mUnpackAlignment));
|
||||
return;
|
||||
|
||||
case dom::WebGLRenderingContext_Binding::UNPACK_FLIP_Y_WEBGL:
|
||||
retval.set(JS::BooleanValue(state.mPixelUnpackState.mFlipY));
|
||||
return;
|
||||
case dom::WebGLRenderingContext_Binding::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
||||
retval.set(JS::BooleanValue(state.mPixelUnpackState.mPremultiplyAlpha));
|
||||
return;
|
||||
case dom::WebGLRenderingContext_Binding::UNPACK_COLORSPACE_CONVERSION_WEBGL:
|
||||
retval.set(
|
||||
JS::NumberValue(state.mPixelUnpackState.mColorspaceConversion));
|
||||
return;
|
||||
|
||||
// -
|
||||
// Array returns
|
||||
|
@ -1948,6 +1968,22 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
|||
case LOCAL_GL_PACK_SKIP_ROWS:
|
||||
retval.set(JS::NumberValue(state.mPixelPackState.skipRows));
|
||||
return;
|
||||
|
||||
case LOCAL_GL_UNPACK_IMAGE_HEIGHT:
|
||||
retval.set(JS::NumberValue(state.mPixelUnpackState.mUnpackImageHeight));
|
||||
return;
|
||||
case LOCAL_GL_UNPACK_ROW_LENGTH:
|
||||
retval.set(JS::NumberValue(state.mPixelUnpackState.mUnpackRowLength));
|
||||
return;
|
||||
case LOCAL_GL_UNPACK_SKIP_IMAGES:
|
||||
retval.set(JS::NumberValue(state.mPixelUnpackState.mUnpackSkipImages));
|
||||
return;
|
||||
case LOCAL_GL_UNPACK_SKIP_PIXELS:
|
||||
retval.set(JS::NumberValue(state.mPixelUnpackState.mUnpackSkipPixels));
|
||||
return;
|
||||
case LOCAL_GL_UNPACK_SKIP_ROWS:
|
||||
retval.set(JS::NumberValue(state.mPixelUnpackState.mUnpackSkipRows));
|
||||
return;
|
||||
} // switch pname
|
||||
} // if webgl2
|
||||
|
||||
|
@ -2075,8 +2111,6 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
|||
case LOCAL_GL_SAMPLE_COVERAGE_INVERT:
|
||||
case LOCAL_GL_SCISSOR_TEST:
|
||||
case LOCAL_GL_STENCIL_TEST:
|
||||
case LOCAL_GL_UNPACK_FLIP_Y_WEBGL:
|
||||
case LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
||||
// WebGL 2:
|
||||
case LOCAL_GL_RASTERIZER_DISCARD:
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE:
|
||||
|
@ -2603,7 +2637,17 @@ void ClientWebGLContext::DepthRange(GLclampf zNear, GLclampf zFar) {
|
|||
Run<RPROC(DepthRange)>(zNear, zFar);
|
||||
}
|
||||
|
||||
void ClientWebGLContext::Flush() { Run<RPROC(Flush)>(); }
|
||||
void ClientWebGLContext::Flush() {
|
||||
const FuncScope funcScope(*this, "flush");
|
||||
const auto notLost = mNotLost;
|
||||
if (IsContextLost()) return;
|
||||
|
||||
Run<RPROC(Flush)>();
|
||||
|
||||
if (notLost->inProcess) return;
|
||||
const auto& child = mNotLost->outOfProcess->mWebGLChild;
|
||||
child->FlushPendingCmds();
|
||||
}
|
||||
|
||||
void ClientWebGLContext::Finish() {
|
||||
if (IsContextLost()) return;
|
||||
|
@ -2650,6 +2694,10 @@ void ClientWebGLContext::LineWidth(GLfloat width) {
|
|||
Run<RPROC(LineWidth)>(width);
|
||||
}
|
||||
|
||||
Maybe<webgl::ErrorInfo> SetPixelUnpack(const bool isWebgl2,
|
||||
WebGLPixelStore* const unpacking,
|
||||
const GLenum pname, const GLint param);
|
||||
|
||||
void ClientWebGLContext::PixelStorei(const GLenum pname, const GLint iparam) {
|
||||
const FuncScope funcScope(*this, "pixelStorei");
|
||||
if (IsContextLost()) return;
|
||||
|
@ -2690,11 +2738,23 @@ void ClientWebGLContext::PixelStorei(const GLenum pname, const GLint iparam) {
|
|||
packState.skipRows = param;
|
||||
return;
|
||||
|
||||
case dom::MOZ_debug_Binding::UNPACK_REQUIRE_FASTPATH:
|
||||
if (!IsSupported(WebGLExtensionID::MOZ_debug)) {
|
||||
EnqueueError_ArgEnum("pname", pname);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Run<RPROC(PixelStorei)>(pname, param);
|
||||
const auto err =
|
||||
SetPixelUnpack(mIsWebGL2, &state.mPixelUnpackState, pname, iparam);
|
||||
if (err) {
|
||||
EnqueueError(*err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientWebGLContext::PolygonOffset(GLfloat factor, GLfloat units) {
|
||||
|
@ -2992,15 +3052,22 @@ void ClientWebGLContext::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
|
|||
|
||||
const auto& child = notLost->outOfProcess->mWebGLChild;
|
||||
child->FlushPendingCmds();
|
||||
mozilla::ipc::Shmem shmem;
|
||||
mozilla::ipc::Shmem rawShmem;
|
||||
if (!child->SendGetBufferSubData(target, srcByteOffset, destView.length(),
|
||||
&shmem))
|
||||
&rawShmem)) {
|
||||
return;
|
||||
if (!shmem.IsReadable()) return;
|
||||
}
|
||||
const webgl::RaiiShmem shmem{child, rawShmem};
|
||||
|
||||
const auto srcView = ByteRange(shmem);
|
||||
MOZ_RELEASE_ASSERT(srcView.length() == destView.length());
|
||||
Memcpy(destView.begin(), srcView.begin(), srcView.length());
|
||||
const auto shmemView = shmem.ByteRange();
|
||||
MOZ_RELEASE_ASSERT(shmemView.length() == 1 + destView.length());
|
||||
|
||||
const auto ok = bool(*(shmemView.begin().get()));
|
||||
const auto srcView =
|
||||
Range<const uint8_t>{shmemView.begin() + 1, shmemView.end()};
|
||||
if (ok) {
|
||||
Memcpy(destView.begin(), srcView.begin(), srcView.length());
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
@ -3736,9 +3803,26 @@ void ClientWebGLContext::TexStorage(uint8_t funcDims, GLenum texTarget,
|
|||
internalFormat, CastUvec3(size));
|
||||
}
|
||||
|
||||
namespace webgl {
|
||||
// TODO: Move these definitions into statics here.
|
||||
Maybe<webgl::TexUnpackBlobDesc> FromImageBitmap(
|
||||
GLenum target, uvec3 size, const dom::ImageBitmap& imageBitmap,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
webgl::TexUnpackBlobDesc FromImageData(GLenum target, uvec3 size,
|
||||
const dom::ImageData& imageData,
|
||||
dom::Uint8ClampedArray* const scopedArr);
|
||||
|
||||
Maybe<webgl::TexUnpackBlobDesc> FromDomElem(const ClientWebGLContext&,
|
||||
GLenum target, uvec3 size,
|
||||
const dom::Element& src,
|
||||
const bool allowBlitImage,
|
||||
ErrorResult* const out_error);
|
||||
} // namespace webgl
|
||||
|
||||
void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
|
||||
GLint level, GLenum respecFormat,
|
||||
const ivec3& offset, const ivec3& size,
|
||||
const ivec3& offset, const ivec3& isize,
|
||||
GLint border, const webgl::PackingInfo& pi,
|
||||
const TexImageSource& src) const {
|
||||
const FuncScope funcScope(*this, "tex(Sub)Image[23]D");
|
||||
|
@ -3751,37 +3835,127 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
|
|||
EnqueueError(LOCAL_GL_INVALID_VALUE, "`border` must be 0.");
|
||||
return;
|
||||
}
|
||||
const auto explicitSize = CastUvec3(isize);
|
||||
|
||||
if (src.mView) {
|
||||
const auto& view = *src.mView;
|
||||
const auto& jsType = view.Type();
|
||||
const auto err = JSTypeMatchUnpackTypeError(pi.type, jsType);
|
||||
switch (err) {
|
||||
case LOCAL_GL_INVALID_ENUM:
|
||||
EnqueueError_ArgEnum("unpackType", pi.type);
|
||||
return;
|
||||
case LOCAL_GL_INVALID_OPERATION:
|
||||
EnqueueError(LOCAL_GL_INVALID_OPERATION,
|
||||
"ArrayBufferView type %s not compatible with `type` %s.",
|
||||
ToString(jsType).c_str(), EnumString(pi.type).c_str());
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
// -
|
||||
|
||||
dom::Uint8ClampedArray scopedArr;
|
||||
|
||||
// -
|
||||
bool isDataUpload = false;
|
||||
auto desc = [&]() -> Maybe<webgl::TexUnpackBlobDesc> {
|
||||
if (src.mPboOffset) {
|
||||
isDataUpload = true;
|
||||
const auto offset = static_cast<uint64_t>(*src.mPboOffset);
|
||||
return Some(webgl::TexUnpackBlobDesc{imageTarget,
|
||||
explicitSize,
|
||||
gfxAlphaType::NonPremult,
|
||||
{},
|
||||
Some(offset)});
|
||||
}
|
||||
|
||||
if (src.mView) {
|
||||
isDataUpload = true;
|
||||
const auto& view = *src.mView;
|
||||
const auto& jsType = view.Type();
|
||||
const auto err = JSTypeMatchUnpackTypeError(pi.type, jsType);
|
||||
switch (err) {
|
||||
case LOCAL_GL_INVALID_ENUM:
|
||||
EnqueueError_ArgEnum("unpackType", pi.type);
|
||||
return {};
|
||||
case LOCAL_GL_INVALID_OPERATION:
|
||||
EnqueueError(LOCAL_GL_INVALID_OPERATION,
|
||||
"ArrayBufferView type %s not compatible with `type` %s.",
|
||||
ToString(jsType).c_str(), EnumString(pi.type).c_str());
|
||||
return {};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const auto range = GetRangeFromView(view, src.mViewElemOffset,
|
||||
src.mViewElemLengthOverride);
|
||||
if (!range) {
|
||||
EnqueueError(LOCAL_GL_INVALID_OPERATION, "`source` too small.");
|
||||
return {};
|
||||
}
|
||||
return Some(webgl::TexUnpackBlobDesc{imageTarget,
|
||||
explicitSize,
|
||||
gfxAlphaType::NonPremult,
|
||||
Some(RawBuffer<>{*range}),
|
||||
{}});
|
||||
}
|
||||
|
||||
if (src.mImageBitmap) {
|
||||
return webgl::FromImageBitmap(imageTarget, explicitSize,
|
||||
*(src.mImageBitmap), src.mOut_error);
|
||||
}
|
||||
|
||||
if (src.mImageData) {
|
||||
return Some(webgl::FromImageData(imageTarget, explicitSize,
|
||||
*(src.mImageData), &scopedArr));
|
||||
}
|
||||
|
||||
if (src.mDomElem) {
|
||||
bool canUseLayerImage = true;
|
||||
if (StaticPrefs::webgl_disable_DOM_blit_uploads()) {
|
||||
canUseLayerImage = false;
|
||||
}
|
||||
if (mNotLost && mNotLost->outOfProcess) {
|
||||
canUseLayerImage = false;
|
||||
}
|
||||
|
||||
return webgl::FromDomElem(*this, imageTarget, explicitSize,
|
||||
*(src.mDomElem), canUseLayerImage,
|
||||
src.mOut_error);
|
||||
}
|
||||
|
||||
return Some(webgl::TexUnpackBlobDesc{
|
||||
imageTarget, explicitSize, gfxAlphaType::NonPremult, {}, {}});
|
||||
}();
|
||||
if (!desc) return;
|
||||
|
||||
// -
|
||||
// Further, for uploads from TexImageSource, implied UNPACK_ROW_LENGTH and
|
||||
// UNPACK_ALIGNMENT are not strictly defined. These restrictions ensure
|
||||
// consistent and efficient behavior regardless of implied UNPACK_ params.
|
||||
|
||||
Maybe<gfx::IntSize> structuredSrcSize;
|
||||
if (desc->surf) {
|
||||
structuredSrcSize = Some(desc->surf->GetSize());
|
||||
}
|
||||
if (desc->image) {
|
||||
structuredSrcSize = Some(desc->image->GetSize());
|
||||
}
|
||||
if (structuredSrcSize) {
|
||||
auto& size = desc->size;
|
||||
if (!size.x) {
|
||||
size.x = structuredSrcSize->width;
|
||||
}
|
||||
if (!size.y) {
|
||||
size.y = structuredSrcSize->height;
|
||||
}
|
||||
}
|
||||
|
||||
const auto notLost =
|
||||
mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF.
|
||||
if (!notLost) return;
|
||||
const auto& inProcessContext = notLost->inProcess;
|
||||
Maybe<std::vector<int>> maybe;
|
||||
if (inProcessContext) {
|
||||
inProcessContext->TexImage(imageTarget, static_cast<uint32_t>(level),
|
||||
respecFormat, CastUvec3(offset), CastUvec3(size),
|
||||
pi, src, *GetCanvas());
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: Remote GetInternalformatParameter");
|
||||
const auto& rawUnpacking = State().mPixelUnpackState;
|
||||
const bool isSubrect =
|
||||
(rawUnpacking.mUnpackImageHeight || rawUnpacking.mUnpackSkipImages ||
|
||||
rawUnpacking.mUnpackRowLength || rawUnpacking.mUnpackSkipRows ||
|
||||
rawUnpacking.mUnpackSkipPixels);
|
||||
if (isDataUpload && isSubrect) {
|
||||
if (rawUnpacking.mFlipY || rawUnpacking.mPremultiplyAlpha) {
|
||||
EnqueueError(LOCAL_GL_INVALID_OPERATION,
|
||||
"Non-DOM-Element uploads with alpha-premult"
|
||||
" or y-flip do not support subrect selection.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
desc->unpacking =
|
||||
rawUnpacking.ForUseWith(desc->imageTarget, desc->size, structuredSrcSize);
|
||||
|
||||
// -
|
||||
|
||||
Run<RPROC(TexImage)>(static_cast<uint32_t>(level), respecFormat,
|
||||
CastUvec3(offset), pi, std::move(*desc));
|
||||
}
|
||||
|
||||
void ClientWebGLContext::CompressedTexImage(bool sub, uint8_t funcDims,
|
||||
|
@ -4314,7 +4488,8 @@ void ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc,
|
|||
if (!res.byteStride) return;
|
||||
const auto& byteStride = res.byteStride;
|
||||
const auto& subrect = res.subrect;
|
||||
const auto& shmemBytes = ByteRange(res.shmem);
|
||||
const webgl::RaiiShmem shmem{child, res.shmem};
|
||||
const auto& shmemBytes = shmem.ByteRange();
|
||||
|
||||
uint8_t bpp;
|
||||
if (!GetBytesPerPixel(desc.pi, &bpp)) {
|
||||
|
@ -4322,21 +4497,27 @@ void ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc,
|
|||
return;
|
||||
}
|
||||
|
||||
const auto& packing = desc.packState;
|
||||
auto packRect = *uvec2::From(subrect.x, subrect.y);
|
||||
packRect.x += packing.skipPixels;
|
||||
packRect.y += packing.skipRows;
|
||||
|
||||
const auto xByteSize = bpp * static_cast<uint32_t>(subrect.width);
|
||||
const ptrdiff_t byteOffset = subrect.y * byteStride + subrect.x * bpp;
|
||||
const ptrdiff_t byteOffset = packRect.y * byteStride + packRect.x * bpp;
|
||||
|
||||
auto srcItr = shmemBytes.begin() + byteOffset;
|
||||
auto destItr = dest.begin() + byteOffset;
|
||||
|
||||
for (const auto i : IntegerRange(subrect.height)) {
|
||||
Unused << i;
|
||||
|
||||
MOZ_RELEASE_ASSERT(srcItr + xByteSize <= shmemBytes.end());
|
||||
MOZ_RELEASE_ASSERT(destItr + xByteSize <= dest.end());
|
||||
if (i) {
|
||||
// Don't trigger an assert on the last loop by pushing a RangedPtr past
|
||||
// its bounds.
|
||||
srcItr += byteStride;
|
||||
destItr += byteStride;
|
||||
MOZ_RELEASE_ASSERT(srcItr + xByteSize <= shmemBytes.end());
|
||||
MOZ_RELEASE_ASSERT(destItr + xByteSize <= dest.end());
|
||||
}
|
||||
Memcpy(destItr, srcItr, xByteSize);
|
||||
|
||||
srcItr += byteStride;
|
||||
destItr += byteStride;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4418,7 +4599,7 @@ void ClientWebGLContext::GetQueryParameter(
|
|||
if (IsContextLost()) return;
|
||||
if (!query.ValidateUsable(*this, "query")) return;
|
||||
|
||||
const auto maybe = [&]() {
|
||||
auto maybe = [&]() {
|
||||
const auto& inProcess = mNotLost->inProcess;
|
||||
if (inProcess) {
|
||||
return inProcess->GetQueryParameter(query.mId, pname);
|
||||
|
@ -4431,17 +4612,26 @@ void ClientWebGLContext::GetQueryParameter(
|
|||
}
|
||||
return ret;
|
||||
}();
|
||||
if (!maybe) return;
|
||||
|
||||
if (maybe) {
|
||||
switch (pname) {
|
||||
case LOCAL_GL_QUERY_RESULT_AVAILABLE:
|
||||
retval.set(JS::BooleanValue(*maybe));
|
||||
break;
|
||||
|
||||
default:
|
||||
retval.set(JS::NumberValue(*maybe));
|
||||
break;
|
||||
// We must usually wait for an event loop before the query can be available.
|
||||
const bool canBeAvailable =
|
||||
(query.mCanBeAvailable || StaticPrefs::webgl_allow_immediate_queries());
|
||||
if (!canBeAvailable) {
|
||||
if (pname != LOCAL_GL_QUERY_RESULT_AVAILABLE) {
|
||||
return;
|
||||
}
|
||||
maybe = Some(0.0);
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_QUERY_RESULT_AVAILABLE:
|
||||
retval.set(JS::BooleanValue(*maybe));
|
||||
break;
|
||||
|
||||
default:
|
||||
retval.set(JS::NumberValue(*maybe));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4498,10 +4688,14 @@ void ClientWebGLContext::EndQuery(const GLenum specificTarget) {
|
|||
EnumString(specificTarget).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto query = slot;
|
||||
slot = nullptr;
|
||||
|
||||
Run<RPROC(EndQuery)>(specificTarget);
|
||||
|
||||
auto& availRunnable = EnsureAvailabilityRunnable();
|
||||
availRunnable.mQueries.push_back(query.get());
|
||||
query->mCanBeAvailable = false;
|
||||
}
|
||||
|
||||
void ClientWebGLContext::QueryCounter(WebGLQueryJS& query,
|
||||
|
@ -4523,6 +4717,10 @@ void ClientWebGLContext::QueryCounter(WebGLQueryJS& query,
|
|||
query.mTarget = target;
|
||||
|
||||
Run<RPROC(QueryCounter)>(query.mId);
|
||||
|
||||
auto& availRunnable = EnsureAvailabilityRunnable();
|
||||
availRunnable.mQueries.push_back(&query);
|
||||
query.mCanBeAvailable = false;
|
||||
}
|
||||
|
||||
// -------------------------------- Sampler -------------------------------
|
||||
|
@ -4661,6 +4859,19 @@ GLenum ClientWebGLContext::ClientWaitSync(WebGLSyncJS& sync,
|
|||
break;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const bool canBeAvailable =
|
||||
(sync.mCanBeAvailable || StaticPrefs::webgl_allow_immediate_queries());
|
||||
if (!canBeAvailable) {
|
||||
if (timeout) {
|
||||
EnqueueWarning(
|
||||
"Sync object not yet queryable. Please wait for the event"
|
||||
" loop.");
|
||||
}
|
||||
return LOCAL_GL_WAIT_FAILED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ class WebGLChild;
|
|||
}
|
||||
|
||||
namespace webgl {
|
||||
class AvailabilityRunnable;
|
||||
class TexUnpackBlob;
|
||||
class TexUnpackBytes;
|
||||
} // namespace webgl
|
||||
|
@ -175,6 +176,7 @@ class ContextGenerationInfo final {
|
|||
std::array<float, 4> mBlendColor = {{0, 0, 0, 0}};
|
||||
std::array<float, 2> mDepthRange = {{0, 1}};
|
||||
webgl::PixelPackState mPixelPackState;
|
||||
WebGLPixelStore mPixelUnpackState;
|
||||
|
||||
std::vector<GLenum> mCompressedTextureFormats;
|
||||
|
||||
|
@ -388,14 +390,19 @@ class WebGLProgramJS final : public nsWrapperCache, public webgl::ObjectJS {
|
|||
|
||||
// -
|
||||
|
||||
class WebGLQueryJS final : public nsWrapperCache, public webgl::ObjectJS {
|
||||
class WebGLQueryJS final : public nsWrapperCache,
|
||||
public webgl::ObjectJS,
|
||||
public SupportsWeakPtr<WebGLQueryJS> {
|
||||
friend class ClientWebGLContext;
|
||||
friend class webgl::AvailabilityRunnable;
|
||||
|
||||
GLenum mTarget = 0; // !IsQuery until Bind
|
||||
bool mCanBeAvailable = false;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQueryJS)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQueryJS)
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLQueryJS)
|
||||
|
||||
explicit WebGLQueryJS(const ClientWebGLContext& webgl)
|
||||
: webgl::ObjectJS(webgl) {}
|
||||
|
@ -483,14 +490,19 @@ class WebGLShaderJS final : public nsWrapperCache, public webgl::ObjectJS {
|
|||
|
||||
// -
|
||||
|
||||
class WebGLSyncJS final : public nsWrapperCache, public webgl::ObjectJS {
|
||||
class WebGLSyncJS final : public nsWrapperCache,
|
||||
public webgl::ObjectJS,
|
||||
public SupportsWeakPtr<WebGLSyncJS> {
|
||||
friend class ClientWebGLContext;
|
||||
friend class webgl::AvailabilityRunnable;
|
||||
|
||||
bool mCanBeAvailable = false;
|
||||
bool mSignaled = false;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSyncJS)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSyncJS)
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLSyncJS)
|
||||
|
||||
explicit WebGLSyncJS(const ClientWebGLContext& webgl)
|
||||
: webgl::ObjectJS(webgl) {}
|
||||
|
@ -694,6 +706,7 @@ struct TexImageSourceAdapter final : public TexImageSource {
|
|||
class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
||||
public nsWrapperCache,
|
||||
public SupportsWeakPtr<ClientWebGLContext> {
|
||||
friend class webgl::AvailabilityRunnable;
|
||||
friend class webgl::ObjectJS;
|
||||
friend class webgl::ProgramKeepAlive;
|
||||
friend class webgl::ShaderKeepAlive;
|
||||
|
@ -753,6 +766,14 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
|||
|
||||
// -
|
||||
|
||||
private:
|
||||
mutable RefPtr<webgl::AvailabilityRunnable> mAvailabilityRunnable;
|
||||
|
||||
public:
|
||||
webgl::AvailabilityRunnable& EnsureAvailabilityRunnable() const;
|
||||
|
||||
// -
|
||||
|
||||
public:
|
||||
void EmulateLoseContext() const;
|
||||
void OnContextLoss(webgl::ContextLossReason) const;
|
||||
|
@ -2105,9 +2126,6 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
|||
// -------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
WebGLPixelStore GetPixelStore() { return mPixelStore; }
|
||||
const WebGLPixelStore GetPixelStore() const { return mPixelStore; }
|
||||
|
||||
// https://immersive-web.github.io/webxr/#xr-compatible
|
||||
bool IsXRCompatible() const;
|
||||
already_AddRefed<dom::Promise> MakeXRCompatible(ErrorResult& aRv);
|
||||
|
@ -2125,7 +2143,6 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
|||
|
||||
bool mResetLayer = true;
|
||||
Maybe<const WebGLContextOptions> mInitialOptions;
|
||||
WebGLPixelStore mPixelStore;
|
||||
bool mXRCompatible = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -425,10 +425,6 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
|
|||
mContext->LinkProgram(*obj);
|
||||
}
|
||||
|
||||
void PixelStorei(GLenum pname, uint32_t param) const {
|
||||
mContext->PixelStorei(pname, param);
|
||||
}
|
||||
|
||||
void PolygonOffset(GLfloat factor, GLfloat units) const {
|
||||
mContext->PolygonOffset(factor, units);
|
||||
}
|
||||
|
@ -570,12 +566,10 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
|
|||
}
|
||||
|
||||
// TexSubImage if `!respecFormat`
|
||||
void TexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
|
||||
const uvec3& offset, const uvec3& size,
|
||||
const webgl::PackingInfo& pi, const TexImageSource& src,
|
||||
const dom::HTMLCanvasElement& canvas) const {
|
||||
mContext->TexImage(imageTarget, level, respecFormat, offset, size, pi, src,
|
||||
canvas);
|
||||
void TexImage(uint32_t level, GLenum respecFormat, const uvec3& offset,
|
||||
const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlobDesc& src) const {
|
||||
mContext->TexImage(level, respecFormat, offset, pi, src);
|
||||
}
|
||||
|
||||
void TexStorage(GLenum texTarget, uint32_t levels, GLenum internalFormat,
|
||||
|
|
|
@ -12,6 +12,7 @@ using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
|
|||
using mozilla::layers::SurfaceDescriptor from "mozilla/layers/LayersTypes.h";
|
||||
using std::string from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::uvec2 from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::Int32Vector from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::CompileResult from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::ContextLossReason from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::FrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h";
|
||||
|
@ -20,11 +21,7 @@ using mozilla::webgl::InitContextDesc from "mozilla/dom/WebGLIpdl.h";
|
|||
using mozilla::webgl::InitContextResult from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::Int32Vector from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::LinkResult from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::MaybeDouble from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::MaybeFrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::MaybeShaderPrecisionFormat from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::MaybeSurfaceDescriptor from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::MaybeString from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::ShaderPrecisionFormat from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::OpaqueFramebufferOptions from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::ReadPixelsDesc from "mozilla/dom/WebGLIpdl.h";
|
||||
using mozilla::webgl::ReadPixelsResultIpc from "mozilla/dom/WebGLIpdl.h";
|
||||
|
@ -58,6 +55,7 @@ parent:
|
|||
|
||||
// -
|
||||
|
||||
sync GetBufferSubData(uint32_t target, uint64_t srcByteOffset, uint64_t byteSize) returns (Shmem ret);
|
||||
sync GetFrontBufferSnapshot() returns (FrontBufferSnapshotIpc ret);
|
||||
sync ReadPixels(ReadPixelsDesc desc, uint64_t maxBytes) returns (ReadPixelsResultIpc ret);
|
||||
|
||||
|
@ -68,28 +66,27 @@ parent:
|
|||
sync CreateOpaqueFramebuffer(uint64_t id, OpaqueFramebufferOptions options) returns (bool ret);
|
||||
sync DrawingBufferSize() returns (uvec2 ret);
|
||||
sync Finish();
|
||||
sync GetBufferParameter(uint32_t target, uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetBufferSubData(uint32_t target, uint64_t srcByteOffset, uint64_t byteSize) returns (Shmem ret);
|
||||
sync GetBufferParameter(uint32_t target, uint32_t pname) returns (double? ret);
|
||||
sync GetCompileResult(uint64_t id) returns (CompileResult ret);
|
||||
sync GetError() returns (uint32_t ret);
|
||||
sync GetFragDataLocation(uint64_t id, string name) returns (int32_t ret);
|
||||
sync GetFramebufferAttachmentParameter(uint64_t id,
|
||||
uint32_t attachment,
|
||||
uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetFrontBuffer(uint64_t fb, bool vr) returns (MaybeSurfaceDescriptor ret);
|
||||
sync GetIndexedParameter(uint32_t target, uint32_t index) returns (MaybeDouble ret);
|
||||
uint32_t pname) returns (double? ret);
|
||||
sync GetFrontBuffer(uint64_t fb, bool vr) returns (SurfaceDescriptor? ret);
|
||||
sync GetIndexedParameter(uint32_t target, uint32_t index) returns (double? ret);
|
||||
sync GetInternalformatParameter(uint32_t target, uint32_t internalFormat, uint32_t pname) returns (Int32Vector? ret);
|
||||
sync GetLinkResult(uint64_t id) returns (LinkResult ret);
|
||||
sync GetNumber(uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetQueryParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetRenderbufferParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetSamplerParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetNumber(uint32_t pname) returns (double? ret);
|
||||
sync GetQueryParameter(uint64_t id, uint32_t pname) returns (double? ret);
|
||||
sync GetRenderbufferParameter(uint64_t id, uint32_t pname) returns (double? ret);
|
||||
sync GetSamplerParameter(uint64_t id, uint32_t pname) returns (double? ret);
|
||||
sync GetShaderPrecisionFormat(
|
||||
uint32_t shaderType, uint32_t precisionType) returns (MaybeShaderPrecisionFormat ret);
|
||||
sync GetString(uint32_t pname) returns (MaybeString ret);
|
||||
sync GetTexParameter(uint64_t id, uint32_t pname) returns (MaybeDouble ret);
|
||||
uint32_t shaderType, uint32_t precisionType) returns (ShaderPrecisionFormat? ret);
|
||||
sync GetString(uint32_t pname) returns (string? ret);
|
||||
sync GetTexParameter(uint64_t id, uint32_t pname) returns (double? ret);
|
||||
sync GetUniform(uint64_t id, uint32_t loc) returns (GetUniformData ret);
|
||||
sync GetVertexAttrib(uint32_t index, uint32_t pname) returns (MaybeDouble ret);
|
||||
sync GetVertexAttrib(uint32_t index, uint32_t pname) returns (double? ret);
|
||||
sync IsEnabled(uint32_t cap) returns (bool ret);
|
||||
sync OnMemoryPressure();
|
||||
sync ValidateProgram(uint64_t id) returns (bool ret);
|
||||
|
|
|
@ -8,15 +8,17 @@
|
|||
#ifndef _QUEUEPARAMTRAITS_H_
|
||||
#define _QUEUEPARAMTRAITS_H_ 1
|
||||
|
||||
#include "mozilla/ipc/SharedMemoryBasic.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/IntegerRange.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/ipc/SharedMemoryBasic.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "nsString.h"
|
||||
#include "WebGLTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
@ -168,6 +170,13 @@ class ProducerView {
|
|||
reinterpret_cast<const uint8_t*>(end));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline QueueStatus WritePod(const T& in) {
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
const auto begin = reinterpret_cast<const uint8_t*>(&in);
|
||||
return Write(begin, begin + sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize aArg using Arg's QueueParamTraits.
|
||||
*/
|
||||
|
@ -213,6 +222,13 @@ class ConsumerView {
|
|||
reinterpret_cast<uint8_t*>(end));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline QueueStatus ReadPod(T* out) {
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
const auto begin = reinterpret_cast<uint8_t*>(out);
|
||||
return Read(begin, begin + sizeof(T));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize aArg using Arg's QueueParamTraits.
|
||||
* If the return value is not Success then aArg is not changed.
|
||||
|
@ -234,19 +250,23 @@ class ConsumerView {
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
QueueStatus ProducerView<T>::Write(const uint8_t* begin, const uint8_t* end) {
|
||||
MOZ_ASSERT(begin);
|
||||
MOZ_ASSERT(begin < end);
|
||||
if (IsSuccess(mStatus)) {
|
||||
QueueStatus ProducerView<T>::Write(const uint8_t* const begin,
|
||||
const uint8_t* const end) {
|
||||
MOZ_ASSERT(begin <= end);
|
||||
if (!mStatus) return mStatus;
|
||||
if (begin < end) {
|
||||
MOZ_ASSERT(begin);
|
||||
mStatus = mProducer->WriteObject(mRead, mWrite, begin, end - begin);
|
||||
}
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QueueStatus ConsumerView<T>::Read(uint8_t* begin, uint8_t* end) {
|
||||
MOZ_ASSERT(begin < end);
|
||||
if (IsSuccess(mStatus)) {
|
||||
QueueStatus ConsumerView<T>::Read(uint8_t* const begin, uint8_t* const end) {
|
||||
MOZ_ASSERT(begin <= end);
|
||||
if (!mStatus) return mStatus;
|
||||
if (begin < end) {
|
||||
MOZ_ASSERT(begin);
|
||||
mStatus = mConsumer->ReadObject(mRead, mWrite, begin, end - begin);
|
||||
}
|
||||
return mStatus;
|
||||
|
@ -336,6 +356,82 @@ struct QueueParamTraits<QueueStatus>
|
|||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
struct QueueParamTraits<webgl::TexUnpackBlobDesc> {
|
||||
using ParamType = webgl::TexUnpackBlobDesc;
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Write(ProducerView<U>& view, const ParamType& in) {
|
||||
MOZ_ASSERT(!in.image);
|
||||
const bool isSurf = bool(in.surf);
|
||||
if (!view.WriteParam(in.imageTarget) || !view.WriteParam(in.size) ||
|
||||
!view.WriteParam(in.srcAlphaType) || !view.WriteParam(in.unpacking) ||
|
||||
!view.WriteParam(in.cpuData) || !view.WriteParam(in.pboOffset) ||
|
||||
!view.WriteParam(isSurf)) {
|
||||
return view.GetStatus();
|
||||
}
|
||||
if (isSurf) {
|
||||
gfx::DataSourceSurface::ScopedMap map(in.surf,
|
||||
gfx::DataSourceSurface::READ);
|
||||
if (!map.IsMapped()) {
|
||||
return QueueStatus::kOOMError;
|
||||
}
|
||||
const auto& surfSize = in.surf->GetSize();
|
||||
const auto stride = *MaybeAs<size_t>(map.GetStride());
|
||||
if (!view.WriteParam(surfSize) ||
|
||||
!view.WriteParam(in.surf->GetFormat()) || !view.WriteParam(stride)) {
|
||||
return view.GetStatus();
|
||||
}
|
||||
|
||||
const size_t dataSize = stride * surfSize.height;
|
||||
const auto& begin = map.GetData();
|
||||
if (!view.Write(begin, begin + dataSize)) {
|
||||
return view.GetStatus();
|
||||
}
|
||||
}
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static QueueStatus Read(ConsumerView<U>& view, ParamType* const out) {
|
||||
bool isSurf;
|
||||
if (!view.ReadParam(&out->imageTarget) || !view.ReadParam(&out->size) ||
|
||||
!view.ReadParam(&out->srcAlphaType) ||
|
||||
!view.ReadParam(&out->unpacking) || !view.ReadParam(&out->cpuData) ||
|
||||
!view.ReadParam(&out->pboOffset) || !view.ReadParam(&isSurf)) {
|
||||
return view.GetStatus();
|
||||
}
|
||||
if (isSurf) {
|
||||
gfx::IntSize surfSize;
|
||||
gfx::SurfaceFormat format;
|
||||
size_t stride;
|
||||
if (!view.ReadParam(&surfSize) || !view.ReadParam(&format) ||
|
||||
!view.ReadParam(&stride)) {
|
||||
return view.GetStatus();
|
||||
}
|
||||
out->surf = gfx::Factory::CreateDataSourceSurfaceWithStride(
|
||||
surfSize, format, stride, true);
|
||||
if (!out->surf) {
|
||||
return QueueStatus::kOOMError;
|
||||
}
|
||||
|
||||
gfx::DataSourceSurface::ScopedMap map(out->surf,
|
||||
gfx::DataSourceSurface::WRITE);
|
||||
if (!map.IsMapped()) {
|
||||
return QueueStatus::kOOMError;
|
||||
}
|
||||
const size_t dataSize = stride * surfSize.height;
|
||||
const auto& begin = map.GetData();
|
||||
if (!view.Read(begin, begin + dataSize)) {
|
||||
return view.GetStatus();
|
||||
}
|
||||
}
|
||||
return QueueStatus::kSuccess;
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
struct QueueParamTraits<nsACString> {
|
||||
using ParamType = nsACString;
|
||||
|
|
|
@ -18,6 +18,31 @@
|
|||
#include "WebGLTexture.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
void WebGLPixelStore::Apply(gl::GLContext& gl, const bool isWebgl2,
|
||||
const uvec3& uploadSize) const {
|
||||
gl.fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mUnpackAlignment);
|
||||
if (!isWebgl2) return;
|
||||
|
||||
// Re-simplify. (ANGLE seems to have an issue with imageHeight ==
|
||||
// uploadSize.y)
|
||||
auto rowLength = mUnpackRowLength;
|
||||
auto imageHeight = mUnpackImageHeight;
|
||||
if (rowLength == uploadSize.x) {
|
||||
rowLength = 0;
|
||||
}
|
||||
if (imageHeight == uploadSize.y) {
|
||||
imageHeight = 0;
|
||||
}
|
||||
|
||||
gl.fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
|
||||
gl.fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, imageHeight);
|
||||
|
||||
gl.fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, mUnpackSkipPixels);
|
||||
gl.fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, mUnpackSkipRows);
|
||||
gl.fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mUnpackSkipImages);
|
||||
}
|
||||
|
||||
namespace webgl {
|
||||
|
||||
static bool IsPIValidForDOM(const webgl::PackingInfo& pi) {
|
||||
|
@ -65,7 +90,7 @@ static bool IsPIValidForDOM(const webgl::PackingInfo& pi) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool ValidatePIForDOM(WebGLContext* webgl,
|
||||
static bool ValidatePIForDOM(const WebGLContext* const webgl,
|
||||
const webgl::PackingInfo& pi) {
|
||||
if (!IsPIValidForDOM(pi)) {
|
||||
webgl->ErrorInvalidValue("Format or type is invalid for DOM sources.");
|
||||
|
@ -178,21 +203,33 @@ static WebGLTexelFormat FormatForPackingInfo(const PackingInfo& pi) {
|
|||
|
||||
////////////////////
|
||||
|
||||
static bool ValidateUnpackPixels(WebGLContext* webgl, uint32_t fullRows,
|
||||
uint32_t tailPixels,
|
||||
webgl::TexUnpackBlob* blob) {
|
||||
if (!blob->mWidth || !blob->mHeight || !blob->mDepth) return true;
|
||||
static uint32_t ZeroOn2D(const GLenum target, const uint32_t val) {
|
||||
const bool is2d = !IsTexTarget3D(target);
|
||||
if (is2d) return 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
|
||||
static bool ValidateUnpackPixels(const WebGLContext* webgl, uint32_t fullRows,
|
||||
uint32_t tailPixels,
|
||||
webgl::TexUnpackBlob* const blob) {
|
||||
const auto& size = blob->mDesc.size;
|
||||
if (!size.x || !size.y || !size.z) return true;
|
||||
|
||||
const auto& unpacking = blob->mDesc.unpacking;
|
||||
|
||||
// -
|
||||
|
||||
const auto usedPixelsPerRow =
|
||||
CheckedUint32(unpacking.mUnpackSkipPixels) + size.x;
|
||||
if (!usedPixelsPerRow.isValid() ||
|
||||
usedPixelsPerRow.value() > blob->mRowLength) {
|
||||
usedPixelsPerRow.value() > unpacking.mUnpackRowLength) {
|
||||
webgl->ErrorInvalidOperation(
|
||||
"UNPACK_SKIP_PIXELS + width >"
|
||||
" UNPACK_ROW_LENGTH.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blob->mHeight > blob->mImageHeight) {
|
||||
if (size.y > unpacking.mUnpackImageHeight) {
|
||||
webgl->ErrorInvalidOperation("height > UNPACK_IMAGE_HEIGHT.");
|
||||
return false;
|
||||
}
|
||||
|
@ -200,14 +237,15 @@ static bool ValidateUnpackPixels(WebGLContext* webgl, uint32_t fullRows,
|
|||
//////
|
||||
|
||||
// The spec doesn't bound SKIP_ROWS + height <= IMAGE_HEIGHT, unfortunately.
|
||||
auto skipFullRows = CheckedUint32(blob->mSkipImages) * blob->mImageHeight;
|
||||
skipFullRows += blob->mSkipRows;
|
||||
auto skipFullRows =
|
||||
CheckedUint32(unpacking.mUnpackSkipImages) * unpacking.mUnpackImageHeight;
|
||||
skipFullRows += unpacking.mUnpackSkipRows;
|
||||
|
||||
MOZ_ASSERT(blob->mDepth >= 1);
|
||||
MOZ_ASSERT(blob->mHeight >= 1);
|
||||
auto usedFullRows = CheckedUint32(blob->mDepth - 1) * blob->mImageHeight;
|
||||
usedFullRows +=
|
||||
blob->mHeight - 1; // Full rows in the final image, excluding the tail.
|
||||
// Full rows in the final image, excluding the tail.
|
||||
MOZ_ASSERT(size.y >= 1);
|
||||
MOZ_ASSERT(size.z >= 1);
|
||||
auto usedFullRows = CheckedUint32(size.z - 1) * unpacking.mUnpackImageHeight;
|
||||
usedFullRows += size.y - 1;
|
||||
|
||||
const auto fullRowsNeeded = skipFullRows + usedFullRows;
|
||||
if (!fullRowsNeeded.isValid()) {
|
||||
|
@ -215,11 +253,14 @@ static bool ValidateUnpackPixels(WebGLContext* webgl, uint32_t fullRows,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (fullRows > fullRowsNeeded.value()) return true;
|
||||
if (fullRows > fullRowsNeeded.value()) {
|
||||
blob->mNeedsExactUpload = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fullRows == fullRowsNeeded.value() &&
|
||||
tailPixels >= usedPixelsPerRow.value()) {
|
||||
blob->mNeedsExactUpload = true;
|
||||
MOZ_ASSERT(blob->mNeedsExactUpload);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -231,15 +272,19 @@ static bool ValidateUnpackPixels(WebGLContext* webgl, uint32_t fullRows,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool ValidateUnpackBytes(WebGLContext* webgl,
|
||||
static bool ValidateUnpackBytes(const WebGLContext* const webgl,
|
||||
const webgl::PackingInfo& pi,
|
||||
size_t availByteCount,
|
||||
webgl::TexUnpackBlob* blob) {
|
||||
if (!blob->mWidth || !blob->mHeight || !blob->mDepth) return true;
|
||||
webgl::TexUnpackBlob* const blob) {
|
||||
const auto& size = blob->mDesc.size;
|
||||
if (!size.x || !size.y || !size.z) return true;
|
||||
const auto& unpacking = blob->mDesc.unpacking;
|
||||
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
|
||||
const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
|
||||
const auto bytesPerRow =
|
||||
CheckedUint32(unpacking.mUnpackRowLength) * bytesPerPixel;
|
||||
const auto rowStride =
|
||||
RoundUpToMultipleOf(bytesPerRow, unpacking.mUnpackAlignment);
|
||||
|
||||
const auto fullRows = availByteCount / rowStride;
|
||||
if (!fullRows.isValid()) {
|
||||
|
@ -255,39 +300,39 @@ static bool ValidateUnpackBytes(WebGLContext* webgl,
|
|||
|
||||
////////////////////
|
||||
|
||||
static uint32_t ZeroOn2D(TexImageTarget target, uint32_t val) {
|
||||
return (IsTarget3D(target) ? val : 0);
|
||||
}
|
||||
// static
|
||||
std::unique_ptr<TexUnpackBlob> TexUnpackBlob::Create(
|
||||
const TexUnpackBlobDesc& desc) {
|
||||
return std::unique_ptr<TexUnpackBlob>{[&]() -> TexUnpackBlob* {
|
||||
if (!IsTarget3D(desc.imageTarget) && desc.size.z != 1) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static uint32_t FallbackOnZero(uint32_t val, uint32_t fallback) {
|
||||
return (val ? val : fallback);
|
||||
}
|
||||
switch (desc.unpacking.mUnpackAlignment) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t rowLength, uint32_t width,
|
||||
uint32_t height, uint32_t depth,
|
||||
gfxAlphaType srcAlphaType)
|
||||
: mAlignment(webgl->mPixelStore.mUnpackAlignment),
|
||||
mRowLength(rowLength),
|
||||
mImageHeight(FallbackOnZero(
|
||||
ZeroOn2D(target, webgl->mPixelStore.mUnpackImageHeight), height))
|
||||
if (desc.image) {
|
||||
return new TexUnpackImage(desc);
|
||||
}
|
||||
if (desc.surf) {
|
||||
return new TexUnpackSurface(desc);
|
||||
}
|
||||
|
||||
,
|
||||
mSkipPixels(webgl->mPixelStore.mUnpackSkipPixels),
|
||||
mSkipRows(webgl->mPixelStore.mUnpackSkipRows),
|
||||
mSkipImages(ZeroOn2D(target, webgl->mPixelStore.mUnpackSkipImages))
|
||||
|
||||
,
|
||||
mWidth(width),
|
||||
mHeight(height),
|
||||
mDepth(depth)
|
||||
|
||||
,
|
||||
mSrcAlphaType(srcAlphaType)
|
||||
|
||||
,
|
||||
mNeedsExactUpload(false) {
|
||||
MOZ_ASSERT_IF(!IsTarget3D(target), mDepth == 1);
|
||||
if (desc.srcAlphaType != gfxAlphaType::NonPremult) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
return new TexUnpackBytes(desc);
|
||||
}()};
|
||||
}
|
||||
|
||||
static bool HasColorAndAlpha(const WebGLTexelFormat format) {
|
||||
|
@ -308,22 +353,25 @@ static bool HasColorAndAlpha(const WebGLTexelFormat format) {
|
|||
}
|
||||
|
||||
bool TexUnpackBlob::ConvertIfNeeded(
|
||||
WebGLContext* webgl, const uint32_t rowLength, const uint32_t rowCount,
|
||||
WebGLTexelFormat srcFormat, const uint8_t* const srcBegin,
|
||||
const ptrdiff_t srcStride, WebGLTexelFormat dstFormat,
|
||||
const ptrdiff_t dstStride, const uint8_t** const out_begin,
|
||||
const WebGLContext* const webgl, const uint32_t rowLength,
|
||||
const uint32_t rowCount, WebGLTexelFormat srcFormat,
|
||||
const uint8_t* const srcBegin, const ptrdiff_t srcStride,
|
||||
WebGLTexelFormat dstFormat, const ptrdiff_t dstStride,
|
||||
const uint8_t** const out_begin,
|
||||
UniqueBuffer* const out_anchoredBuffer) const {
|
||||
MOZ_ASSERT(srcFormat != WebGLTexelFormat::FormatNotSupportingAnyConversion);
|
||||
MOZ_ASSERT(dstFormat != WebGLTexelFormat::FormatNotSupportingAnyConversion);
|
||||
|
||||
*out_begin = srcBegin;
|
||||
|
||||
const auto& unpacking = mDesc.unpacking;
|
||||
|
||||
if (!rowLength || !rowCount) return true;
|
||||
|
||||
const auto srcIsPremult = (mSrcAlphaType == gfxAlphaType::Premult);
|
||||
const auto& dstIsPremult = webgl->mPixelStore.mPremultiplyAlpha;
|
||||
const auto srcIsPremult = (mDesc.srcAlphaType == gfxAlphaType::Premult);
|
||||
const auto& dstIsPremult = unpacking.mPremultiplyAlpha;
|
||||
const auto fnHasPremultMismatch = [&]() {
|
||||
if (mSrcAlphaType == gfxAlphaType::Opaque) return false;
|
||||
if (mDesc.srcAlphaType == gfxAlphaType::Opaque) return false;
|
||||
|
||||
if (!HasColorAndAlpha(srcFormat)) return false;
|
||||
|
||||
|
@ -331,8 +379,7 @@ bool TexUnpackBlob::ConvertIfNeeded(
|
|||
};
|
||||
|
||||
const auto srcOrigin =
|
||||
(webgl->mPixelStore.mFlipY ? gl::OriginPos::TopLeft
|
||||
: gl::OriginPos::BottomLeft);
|
||||
(unpacking.mFlipY ? gl::OriginPos::TopLeft : gl::OriginPos::BottomLeft);
|
||||
const auto dstOrigin = gl::OriginPos::BottomLeft;
|
||||
|
||||
if (srcFormat != dstFormat) {
|
||||
|
@ -399,66 +446,77 @@ static GLenum DoTexOrSubImage(bool isSubImage, gl::GLContext* gl,
|
|||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackBytes
|
||||
|
||||
TexUnpackBytes::TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
bool isClientData, const uint8_t* ptr,
|
||||
size_t availBytes)
|
||||
: TexUnpackBlob(webgl, target,
|
||||
FallbackOnZero(webgl->mPixelStore.mUnpackRowLength, width),
|
||||
width, height, depth, gfxAlphaType::NonPremult),
|
||||
mIsClientData(isClientData),
|
||||
mPtr(ptr),
|
||||
mAvailBytes(availBytes) {}
|
||||
|
||||
bool TexUnpackBytes::Validate(WebGLContext* webgl,
|
||||
bool TexUnpackBytes::Validate(const WebGLContext* const webgl,
|
||||
const webgl::PackingInfo& pi) {
|
||||
if (mIsClientData && !mPtr) return true;
|
||||
if (!HasData()) return true;
|
||||
|
||||
return ValidateUnpackBytes(webgl, pi, mAvailBytes, this);
|
||||
CheckedInt<size_t> availBytes = 0;
|
||||
if (mDesc.cpuData) {
|
||||
const auto& range = mDesc.cpuData->Data();
|
||||
availBytes = range.length();
|
||||
} else if (mDesc.pboOffset) {
|
||||
const auto& pboOffset = *mDesc.pboOffset;
|
||||
|
||||
const auto& pbo =
|
||||
webgl->ValidateBufferSelection(LOCAL_GL_PIXEL_UNPACK_BUFFER);
|
||||
if (!pbo) return false; // Might be invalid e.g. due to in-use by TF.
|
||||
availBytes = pbo->ByteLength();
|
||||
availBytes -= pboOffset;
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Must be one of the above");
|
||||
}
|
||||
if (!availBytes.isValid()) {
|
||||
webgl->ErrorInvalidOperation("Offset is passed end of buffer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ValidateUnpackBytes(webgl, pi, availBytes.value(), this);
|
||||
}
|
||||
|
||||
bool TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi,
|
||||
GLenum* const out_error) const {
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
const auto& webgl = tex->mContext;
|
||||
const auto& target = mDesc.imageTarget;
|
||||
const auto& size = mDesc.size;
|
||||
const auto& unpacking = mDesc.unpacking;
|
||||
|
||||
const auto format = FormatForPackingInfo(pi);
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
|
||||
const uint8_t* uploadPtr = mPtr;
|
||||
const uint8_t dummy = 0;
|
||||
const uint8_t* uploadPtr = nullptr;
|
||||
if (mDesc.cpuData) {
|
||||
const auto range = mDesc.cpuData->Data();
|
||||
uploadPtr = range.begin().get();
|
||||
if (!uploadPtr) {
|
||||
MOZ_ASSERT(!range.length());
|
||||
uploadPtr = &dummy;
|
||||
}
|
||||
}
|
||||
|
||||
UniqueBuffer tempBuffer;
|
||||
|
||||
do {
|
||||
if (!mIsClientData || !mPtr) break;
|
||||
if (mDesc.pboOffset || !uploadPtr) break;
|
||||
|
||||
if (!webgl->mPixelStore.mFlipY && !webgl->mPixelStore.mPremultiplyAlpha) {
|
||||
if (!unpacking.mFlipY && !unpacking.mPremultiplyAlpha) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (webgl->mPixelStore.mUnpackImageHeight ||
|
||||
webgl->mPixelStore.mUnpackSkipImages ||
|
||||
webgl->mPixelStore.mUnpackRowLength ||
|
||||
webgl->mPixelStore.mUnpackSkipRows ||
|
||||
webgl->mPixelStore.mUnpackSkipPixels) {
|
||||
webgl->ErrorInvalidOperation(
|
||||
"Non-DOM-Element uploads with alpha-premult"
|
||||
" or y-flip do not support subrect selection.");
|
||||
return false;
|
||||
}
|
||||
|
||||
webgl->GenerateWarning(
|
||||
"Alpha-premult and y-flip are deprecated for"
|
||||
" non-DOM-Element uploads.");
|
||||
|
||||
const uint32_t rowLength = mWidth;
|
||||
const uint32_t rowCount = mHeight * mDepth;
|
||||
const auto stride =
|
||||
RoundUpToMultipleOf(rowLength * bytesPerPixel, mAlignment);
|
||||
if (!ConvertIfNeeded(webgl, rowLength, rowCount, format, mPtr, stride,
|
||||
const uint32_t rowLength = size.x;
|
||||
const uint32_t rowCount = size.y * size.z;
|
||||
const auto stride = RoundUpToMultipleOf(rowLength * bytesPerPixel,
|
||||
unpacking.mUnpackAlignment);
|
||||
const auto srcPtr = uploadPtr;
|
||||
if (!ConvertIfNeeded(webgl, rowLength, rowCount, format, srcPtr, stride,
|
||||
format, stride, &uploadPtr, &tempBuffer)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -488,7 +546,7 @@ bool TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
|
||||
*out_error =
|
||||
DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, mDepth, uploadPtr);
|
||||
zOffset, size.x, size.y, size.z, uploadPtr);
|
||||
|
||||
if (webgl->mBoundPixelUnpackBuffer) {
|
||||
gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
@ -505,7 +563,7 @@ bool TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
AssertUintParamCorrect(gl, LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
*out_error =
|
||||
DoTexOrSubImage(false, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, mDepth, nullptr);
|
||||
zOffset, size.x, size.y, size.z, nullptr);
|
||||
if (*out_error) return true;
|
||||
}
|
||||
|
||||
|
@ -516,32 +574,36 @@ bool TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
|
||||
// Make our sometimes-implicit values explicit. Also this keeps them constant
|
||||
// when we ask for height=mHeight-1 and such.
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mRowLength);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mImageHeight);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, unpacking.mUnpackRowLength);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, unpacking.mUnpackImageHeight);
|
||||
|
||||
if (mDepth > 1) {
|
||||
if (size.z > 1) {
|
||||
*out_error =
|
||||
DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset, zOffset,
|
||||
mWidth, mHeight, mDepth - 1, uploadPtr);
|
||||
size.x, size.y, size.z - 1, uploadPtr);
|
||||
}
|
||||
|
||||
// Skip the images we uploaded.
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mSkipImages + mDepth - 1);
|
||||
const auto skipImages = ZeroOn2D(target, unpacking.mUnpackSkipImages);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, skipImages + size.z - 1);
|
||||
|
||||
if (mHeight > 1) {
|
||||
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset + mDepth - 1, mWidth, mHeight - 1, 1,
|
||||
uploadPtr);
|
||||
if (size.y > 1) {
|
||||
*out_error =
|
||||
DoTexOrSubImage(true, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset + size.z - 1, size.x, size.y - 1, 1, uploadPtr);
|
||||
}
|
||||
|
||||
const auto totalSkipRows =
|
||||
CheckedUint32(mSkipImages) * mImageHeight + mSkipRows;
|
||||
CheckedUint32(skipImages) * unpacking.mUnpackImageHeight +
|
||||
unpacking.mUnpackSkipRows;
|
||||
const auto totalFullRows =
|
||||
CheckedUint32(mDepth - 1) * mImageHeight + mHeight - 1;
|
||||
CheckedUint32(size.z - 1) * unpacking.mUnpackImageHeight + size.y - 1;
|
||||
const auto tailOffsetRows = totalSkipRows + totalFullRows;
|
||||
|
||||
const auto bytesPerRow = CheckedUint32(mRowLength) * bytesPerPixel;
|
||||
const auto rowStride = RoundUpToMultipleOf(bytesPerRow, mAlignment);
|
||||
const auto bytesPerRow =
|
||||
CheckedUint32(unpacking.mUnpackRowLength) * bytesPerPixel;
|
||||
const auto rowStride =
|
||||
RoundUpToMultipleOf(bytesPerRow, unpacking.mUnpackAlignment);
|
||||
if (!rowStride.isValid()) {
|
||||
MOZ_CRASH("Should be checked earlier.");
|
||||
}
|
||||
|
@ -559,20 +621,10 @@ bool TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
// Keep skipping pixels though!
|
||||
|
||||
*out_error = DoTexOrSubImage(true, gl, target, level, dui, xOffset,
|
||||
yOffset + mHeight - 1, zOffset + mDepth - 1,
|
||||
mWidth, 1, 1, uploadPtr);
|
||||
yOffset + size.y - 1, zOffset + size.z - 1,
|
||||
size.x, 1, 1, uploadPtr);
|
||||
|
||||
// Reset all our modified state.
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
|
||||
webgl->mPixelStore.mUnpackAlignment);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT,
|
||||
webgl->mPixelStore.mUnpackImageHeight);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH,
|
||||
webgl->mPixelStore.mUnpackRowLength);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES,
|
||||
webgl->mPixelStore.mUnpackSkipImages);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS,
|
||||
webgl->mPixelStore.mUnpackSkipRows);
|
||||
// Caller will reset all our modified PixelStorei state.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -581,46 +633,42 @@ bool TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackImage
|
||||
|
||||
TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
layers::Image* image, gfxAlphaType srcAlphaType)
|
||||
: TexUnpackBlob(webgl, target, image->GetSize().width, width, height, depth,
|
||||
srcAlphaType),
|
||||
mImage(image) {}
|
||||
|
||||
TexUnpackImage::~TexUnpackImage() = default;
|
||||
|
||||
bool TexUnpackImage::Validate(WebGLContext* webgl,
|
||||
bool TexUnpackImage::Validate(const WebGLContext* const webgl,
|
||||
const webgl::PackingInfo& pi) {
|
||||
if (!ValidatePIForDOM(webgl, pi)) return false;
|
||||
|
||||
const auto fullRows = mImage->GetSize().height;
|
||||
const auto fullRows = mDesc.image->GetSize().height;
|
||||
return ValidateUnpackPixels(webgl, fullRows, 0, this);
|
||||
}
|
||||
|
||||
bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi,
|
||||
GLenum* const out_error) const {
|
||||
MOZ_ASSERT_IF(needsRespec, !isSubImage);
|
||||
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
const auto& webgl = tex->mContext;
|
||||
const auto& target = mDesc.imageTarget;
|
||||
const auto& size = mDesc.size;
|
||||
const auto& image = mDesc.image;
|
||||
const auto& unpacking = mDesc.unpacking;
|
||||
|
||||
gl::GLContext* gl = webgl->GL();
|
||||
const auto& gl = webgl->GL();
|
||||
|
||||
if (needsRespec) {
|
||||
*out_error =
|
||||
DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth, nullptr);
|
||||
DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, size.x, size.y, size.z, nullptr);
|
||||
if (*out_error) return true;
|
||||
}
|
||||
|
||||
const char* fallbackReason;
|
||||
do {
|
||||
if (mDepth != 1) {
|
||||
if (size.z != 1) {
|
||||
fallbackReason = "depth is not 1";
|
||||
break;
|
||||
}
|
||||
|
@ -629,18 +677,17 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
break;
|
||||
}
|
||||
|
||||
if (webgl->mPixelStore.mUnpackSkipPixels ||
|
||||
webgl->mPixelStore.mUnpackSkipRows ||
|
||||
webgl->mPixelStore.mUnpackSkipImages) {
|
||||
if (unpacking.mUnpackSkipPixels || unpacking.mUnpackSkipRows ||
|
||||
unpacking.mUnpackSkipImages) {
|
||||
fallbackReason = "non-zero UNPACK_SKIP_* not yet supported";
|
||||
break;
|
||||
}
|
||||
|
||||
const auto fnHasPremultMismatch = [&]() {
|
||||
if (mSrcAlphaType == gfxAlphaType::Opaque) return false;
|
||||
if (mDesc.srcAlphaType == gfxAlphaType::Opaque) return false;
|
||||
|
||||
const bool srcIsPremult = (mSrcAlphaType == gfxAlphaType::Premult);
|
||||
const auto& dstIsPremult = webgl->mPixelStore.mPremultiplyAlpha;
|
||||
const bool srcIsPremult = (mDesc.srcAlphaType == gfxAlphaType::Premult);
|
||||
const auto& dstIsPremult = unpacking.mPremultiplyAlpha;
|
||||
if (srcIsPremult == dstIsPremult) return false;
|
||||
|
||||
if (dstIsPremult) {
|
||||
|
@ -670,7 +717,7 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
gl::GLContext::LocalErrorScope errorScope(*gl);
|
||||
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0, target.get(),
|
||||
LOCAL_GL_COLOR_ATTACHMENT0, target,
|
||||
tex->mGLName, level);
|
||||
|
||||
if (errorScope.GetError()) {
|
||||
|
@ -685,11 +732,10 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
break;
|
||||
}
|
||||
|
||||
const gfx::IntSize dstSize(mWidth, mHeight);
|
||||
const auto dstOrigin =
|
||||
(webgl->mPixelStore.mFlipY ? gl::OriginPos::TopLeft
|
||||
: gl::OriginPos::BottomLeft);
|
||||
if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, dstSize, dstOrigin)) {
|
||||
(unpacking.mFlipY ? gl::OriginPos::TopLeft : gl::OriginPos::BottomLeft);
|
||||
if (!gl->BlitHelper()->BlitImageToFramebuffer(image, {size.x, size.y},
|
||||
dstOrigin)) {
|
||||
fallbackReason = "likely bug: failed to blit";
|
||||
break;
|
||||
}
|
||||
|
@ -701,9 +747,9 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
|
||||
const nsPrintfCString perfMsg(
|
||||
"Failed to hit GPU-copy fast-path: %s (src type %u)", fallbackReason,
|
||||
uint32_t(mImage->GetFormat()));
|
||||
uint32_t(image->GetFormat()));
|
||||
|
||||
if (webgl->mPixelStore.mRequireFastPath) {
|
||||
if (unpacking.mRequireFastPath) {
|
||||
webgl->ErrorInvalidOperation("%s", perfMsg.BeginReading());
|
||||
return false;
|
||||
}
|
||||
|
@ -711,7 +757,7 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
webgl->GeneratePerfWarning("%s Falling back to CPU upload.",
|
||||
perfMsg.BeginReading());
|
||||
|
||||
const RefPtr<gfx::SourceSurface> surf = mImage->GetAsSourceSurface();
|
||||
const RefPtr<gfx::SourceSurface> surf = image->GetAsSourceSurface();
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> dataSurf;
|
||||
if (surf) {
|
||||
|
@ -725,29 +771,22 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
return false;
|
||||
}
|
||||
|
||||
const TexUnpackSurface surfBlob(webgl, target, mWidth, mHeight, mDepth,
|
||||
dataSurf, mSrcAlphaType);
|
||||
|
||||
return surfBlob.TexOrSubImage(isSubImage, needsRespec, tex, target, level,
|
||||
dui, xOffset, yOffset, zOffset, pi, out_error);
|
||||
const TexUnpackBlobDesc newDesc = {
|
||||
target, size, mDesc.srcAlphaType, {}, {}, {}, dataSurf, unpacking};
|
||||
const TexUnpackSurface surfBlob(newDesc);
|
||||
return surfBlob.TexOrSubImage(isSubImage, needsRespec, tex, level, dui,
|
||||
xOffset, yOffset, zOffset, pi, out_error);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackSurface
|
||||
|
||||
TexUnpackSurface::TexUnpackSurface(const WebGLContext* webgl,
|
||||
TexImageTarget target, uint32_t width,
|
||||
uint32_t height, uint32_t depth,
|
||||
gfx::DataSourceSurface* surf,
|
||||
gfxAlphaType srcAlphaType)
|
||||
: TexUnpackBlob(webgl, target, surf->GetSize().width, width, height, depth,
|
||||
srcAlphaType),
|
||||
mSurf(surf) {}
|
||||
TexUnpackSurface::~TexUnpackSurface() = default;
|
||||
|
||||
//////////
|
||||
|
||||
static bool GetFormatForSurf(gfx::SourceSurface* surf,
|
||||
static bool GetFormatForSurf(const gfx::SourceSurface* surf,
|
||||
WebGLTexelFormat* const out_texelFormat,
|
||||
uint8_t* const out_bpp) {
|
||||
const auto surfFormat = surf->GetFormat();
|
||||
|
@ -796,25 +835,29 @@ static bool GetFormatForSurf(gfx::SourceSurface* surf,
|
|||
|
||||
//////////
|
||||
|
||||
bool TexUnpackSurface::Validate(WebGLContext* webgl,
|
||||
bool TexUnpackSurface::Validate(const WebGLContext* const webgl,
|
||||
const webgl::PackingInfo& pi) {
|
||||
if (!ValidatePIForDOM(webgl, pi)) return false;
|
||||
|
||||
const auto fullRows = mSurf->GetSize().height;
|
||||
const auto fullRows = mDesc.surf->GetSize().height;
|
||||
return ValidateUnpackPixels(webgl, fullRows, 0, this);
|
||||
}
|
||||
|
||||
bool TexUnpackSurface::TexOrSubImage(
|
||||
bool isSubImage, bool needsRespec, WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level, const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, const webgl::PackingInfo& dstPI,
|
||||
GLenum* const out_error) const {
|
||||
bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset,
|
||||
GLint zOffset,
|
||||
const webgl::PackingInfo& dstPI,
|
||||
GLenum* const out_error) const {
|
||||
const auto& webgl = tex->mContext;
|
||||
const auto& size = mDesc.size;
|
||||
auto& surf = *(mDesc.surf);
|
||||
|
||||
////
|
||||
|
||||
const auto rowLength = mSurf->GetSize().width;
|
||||
const auto rowCount = mSurf->GetSize().height;
|
||||
const auto rowLength = surf.GetSize().width;
|
||||
const auto rowCount = surf.GetSize().height;
|
||||
|
||||
const auto& dstBPP = webgl::BytesPerPixel(dstPI);
|
||||
const auto dstFormat = FormatForPackingInfo(dstPI);
|
||||
|
@ -823,15 +866,15 @@ bool TexUnpackSurface::TexOrSubImage(
|
|||
|
||||
WebGLTexelFormat srcFormat;
|
||||
uint8_t srcBPP;
|
||||
if (!GetFormatForSurf(mSurf, &srcFormat, &srcBPP)) {
|
||||
if (!GetFormatForSurf(&surf, &srcFormat, &srcBPP)) {
|
||||
webgl->ErrorImplementationBug(
|
||||
"GetFormatForSurf failed for"
|
||||
" WebGLTexelFormat::%u.",
|
||||
uint32_t(mSurf->GetFormat()));
|
||||
uint32_t(surf.GetFormat()));
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::DataSourceSurface::ScopedMap map(mSurf,
|
||||
gfx::DataSourceSurface::ScopedMap map(&surf,
|
||||
gfx::DataSourceSurface::MapType::READ);
|
||||
if (!map.IsMapped()) {
|
||||
webgl->ErrorOutOfMemory("Failed to map source surface for upload.");
|
||||
|
@ -882,15 +925,10 @@ bool TexUnpackSurface::TexOrSubImage(
|
|||
}
|
||||
|
||||
*out_error =
|
||||
DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth, dstBegin);
|
||||
DoTexOrSubImage(isSubImage, gl, mDesc.imageTarget, level, dui, xOffset,
|
||||
yOffset, zOffset, size.x, size.y, size.z, dstBegin);
|
||||
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
|
||||
webgl->mPixelStore.mUnpackAlignment);
|
||||
if (webgl->IsWebGL2()) {
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH,
|
||||
webgl->mPixelStore.mUnpackRowLength);
|
||||
}
|
||||
// Caller will reset all our modified PixelStorei state.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ class Image;
|
|||
class ImageContainer;
|
||||
} // namespace layers
|
||||
|
||||
bool IsTarget3D(TexImageTarget target);
|
||||
|
||||
namespace webgl {
|
||||
|
||||
struct PackingInfo;
|
||||
|
@ -39,30 +41,21 @@ struct DriverUnpackInfo;
|
|||
|
||||
class TexUnpackBlob {
|
||||
public:
|
||||
const uint32_t mAlignment;
|
||||
const uint32_t mRowLength;
|
||||
const uint32_t mImageHeight;
|
||||
const uint32_t mSkipPixels;
|
||||
const uint32_t mSkipRows;
|
||||
const uint32_t mSkipImages;
|
||||
const uint32_t mWidth;
|
||||
const uint32_t mHeight;
|
||||
const uint32_t mDepth;
|
||||
const TexUnpackBlobDesc& mDesc;
|
||||
bool mNeedsExactUpload = true;
|
||||
|
||||
const gfxAlphaType mSrcAlphaType;
|
||||
|
||||
bool mNeedsExactUpload;
|
||||
static std::unique_ptr<TexUnpackBlob> Create(const TexUnpackBlobDesc&);
|
||||
|
||||
protected:
|
||||
TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t rowLength, uint32_t width, uint32_t height,
|
||||
uint32_t depth, gfxAlphaType srcAlphaType);
|
||||
explicit TexUnpackBlob(const TexUnpackBlobDesc& desc) : mDesc(desc) {
|
||||
MOZ_ASSERT_IF(!IsTarget3D(mDesc.imageTarget), mDesc.size.z == 1);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~TexUnpackBlob() = default;
|
||||
|
||||
protected:
|
||||
bool ConvertIfNeeded(WebGLContext* webgl, const uint32_t rowLength,
|
||||
bool ConvertIfNeeded(const WebGLContext*, const uint32_t rowLength,
|
||||
const uint32_t rowCount, WebGLTexelFormat srcFormat,
|
||||
const uint8_t* const srcBegin, const ptrdiff_t srcStride,
|
||||
WebGLTexelFormat dstFormat, const ptrdiff_t dstStride,
|
||||
|
@ -73,75 +66,67 @@ class TexUnpackBlob {
|
|||
public:
|
||||
virtual bool HasData() const { return true; }
|
||||
|
||||
virtual bool Validate(WebGLContext* webgl, const webgl::PackingInfo& pi) = 0;
|
||||
virtual bool Validate(const WebGLContext*, const webgl::PackingInfo& pi) = 0;
|
||||
|
||||
// Returns false when we've generated a WebGL error.
|
||||
// Returns true but with a non-zero *out_error if we still need to generate a
|
||||
// WebGL error.
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level, const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi,
|
||||
GLenum* const out_error) const = 0;
|
||||
};
|
||||
|
||||
class TexUnpackBytes final : public TexUnpackBlob {
|
||||
public:
|
||||
const bool mIsClientData;
|
||||
const uint8_t* const mPtr;
|
||||
const size_t mAvailBytes;
|
||||
explicit TexUnpackBytes(const TexUnpackBlobDesc& desc) : TexUnpackBlob(desc) {
|
||||
MOZ_ASSERT(mDesc.srcAlphaType == gfxAlphaType::NonPremult);
|
||||
}
|
||||
|
||||
TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
bool isClientData, const uint8_t* ptr, size_t availBytes);
|
||||
virtual bool HasData() const override {
|
||||
return mDesc.pboOffset || mDesc.cpuData;
|
||||
}
|
||||
|
||||
virtual bool HasData() const override { return !mIsClientData || bool(mPtr); }
|
||||
|
||||
virtual bool Validate(WebGLContext* webgl,
|
||||
virtual bool Validate(const WebGLContext*,
|
||||
const webgl::PackingInfo& pi) override;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level, const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi,
|
||||
GLenum* const out_error) const override;
|
||||
};
|
||||
|
||||
class TexUnpackImage final : public TexUnpackBlob {
|
||||
public:
|
||||
const RefPtr<layers::Image> mImage;
|
||||
|
||||
TexUnpackImage(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
layers::Image* image, gfxAlphaType srcAlphaType);
|
||||
|
||||
explicit TexUnpackImage(const TexUnpackBlobDesc& desc)
|
||||
: TexUnpackBlob(desc) {}
|
||||
~TexUnpackImage(); // Prevent needing to define layers::Image in the header.
|
||||
|
||||
virtual bool Validate(WebGLContext* webgl,
|
||||
virtual bool Validate(const WebGLContext*,
|
||||
const webgl::PackingInfo& pi) override;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level, const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& dstPI,
|
||||
GLenum* const out_error) const override;
|
||||
};
|
||||
|
||||
class TexUnpackSurface final : public TexUnpackBlob {
|
||||
public:
|
||||
const RefPtr<gfx::DataSourceSurface> mSurf;
|
||||
explicit TexUnpackSurface(const TexUnpackBlobDesc& desc)
|
||||
: TexUnpackBlob(desc) {}
|
||||
~TexUnpackSurface();
|
||||
|
||||
TexUnpackSurface(const WebGLContext* webgl, TexImageTarget target,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
gfx::DataSourceSurface* surf, gfxAlphaType srcAlphaType);
|
||||
|
||||
virtual bool Validate(WebGLContext* webgl,
|
||||
virtual bool Validate(const WebGLContext*,
|
||||
const webgl::PackingInfo& pi) override;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec,
|
||||
WebGLTexture* tex, TexImageTarget target,
|
||||
GLint level, const webgl::DriverUnpackInfo* dui,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
WebGLTexture* tex, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& dstPI,
|
||||
GLenum* const out_error) const override;
|
||||
};
|
||||
|
|
|
@ -67,26 +67,12 @@ Maybe<double> WebGL2Context::GetParameter(GLenum pname) {
|
|||
case LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS:
|
||||
case LOCAL_GL_MAX_VERTEX_UNIFORM_BLOCKS:
|
||||
case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS:
|
||||
case LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET:
|
||||
case LOCAL_GL_PACK_ROW_LENGTH:
|
||||
case LOCAL_GL_PACK_SKIP_PIXELS:
|
||||
case LOCAL_GL_PACK_SKIP_ROWS:
|
||||
case LOCAL_GL_UNPACK_IMAGE_HEIGHT:
|
||||
case LOCAL_GL_UNPACK_ROW_LENGTH: {
|
||||
case LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET: {
|
||||
GLint val;
|
||||
gl->fGetIntegerv(pname, &val);
|
||||
return Some(val);
|
||||
}
|
||||
|
||||
case LOCAL_GL_UNPACK_SKIP_IMAGES:
|
||||
return Some(mPixelStore.mUnpackSkipImages);
|
||||
|
||||
case LOCAL_GL_UNPACK_SKIP_PIXELS:
|
||||
return Some(mPixelStore.mUnpackSkipPixels);
|
||||
|
||||
case LOCAL_GL_UNPACK_SKIP_ROWS:
|
||||
return Some(mPixelStore.mUnpackSkipRows);
|
||||
|
||||
case LOCAL_GL_MAX_VARYING_COMPONENTS: {
|
||||
// On OS X Core Profile this is buggy. The spec says that the
|
||||
// value is 4 * GL_MAX_VARYING_VECTORS
|
||||
|
|
|
@ -29,10 +29,6 @@ RefPtr<WebGLSync> WebGL2Context::FenceSync(GLenum condition, GLbitfield flags) {
|
|||
}
|
||||
|
||||
RefPtr<WebGLSync> globj = new WebGLSync(this, condition, flags);
|
||||
|
||||
const auto& availRunnable = EnsureAvailabilityRunnable();
|
||||
availRunnable->mSyncs.push_back(globj);
|
||||
|
||||
return globj;
|
||||
}
|
||||
|
||||
|
@ -54,17 +50,6 @@ GLenum WebGL2Context::ClientWaitSync(const WebGLSync& sync, GLbitfield flags,
|
|||
return LOCAL_GL_WAIT_FAILED;
|
||||
}
|
||||
|
||||
const bool canBeAvailable =
|
||||
(sync.mCanBeAvailable || StaticPrefs::webgl_allow_immediate_queries());
|
||||
if (!canBeAvailable) {
|
||||
if (timeout) {
|
||||
GenerateWarning(
|
||||
"Sync object not yet queryable. Please wait for the event"
|
||||
" loop.");
|
||||
}
|
||||
return LOCAL_GL_WAIT_FAILED;
|
||||
}
|
||||
|
||||
const auto ret = gl->fClientWaitSync(sync.mGLName, flags, timeout);
|
||||
|
||||
if (ret == LOCAL_GL_CONDITION_SATISFIED || ret == LOCAL_GL_ALREADY_SIGNALED) {
|
||||
|
|
|
@ -11,68 +11,71 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
WebGLChild::WebGLChild(ClientWebGLContext& context)
|
||||
: PcqActor(this), mContext(context) {}
|
||||
WebGLChild::WebGLChild(ClientWebGLContext& context) : mContext(&context) {}
|
||||
|
||||
WebGLChild::~WebGLChild() { (void)Send__delete__(this); }
|
||||
|
||||
// -
|
||||
|
||||
static constexpr size_t kDefaultCmdsShmemSize = 100 * 1000;
|
||||
|
||||
Maybe<Range<uint8_t>> WebGLChild::AllocPendingCmdBytes(const size_t size) {
|
||||
if (!mPendingCmds) {
|
||||
mPendingCmds.reset(new webgl::ShmemCmdBuffer);
|
||||
size_t capacity = 1000 * 1000;
|
||||
if (!mPendingCmdsShmem) {
|
||||
size_t capacity = kDefaultCmdsShmemSize;
|
||||
if (capacity < size) {
|
||||
capacity = size;
|
||||
}
|
||||
|
||||
if (!PWebGLChild::AllocShmem(
|
||||
capacity, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
|
||||
&(mPendingCmds->mShmem))) {
|
||||
return {};
|
||||
}
|
||||
auto shmem = webgl::RaiiShmem::Alloc(
|
||||
this, capacity,
|
||||
mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC);
|
||||
MOZ_ASSERT(shmem);
|
||||
if (!shmem) return {};
|
||||
mPendingCmdsShmem = std::move(shmem);
|
||||
mPendingCmdsPos = 0;
|
||||
}
|
||||
|
||||
auto remaining = mPendingCmds->Remaining();
|
||||
const auto range = mPendingCmdsShmem.ByteRange();
|
||||
|
||||
const auto remaining =
|
||||
Range<uint8_t>{range.begin() + mPendingCmdsPos, range.end()};
|
||||
if (size > remaining.length()) {
|
||||
FlushPendingCmds();
|
||||
return AllocPendingCmdBytes(size);
|
||||
}
|
||||
mPendingCmds->mPos += size;
|
||||
mPendingCmdsPos += size;
|
||||
return Some(Range<uint8_t>{remaining.begin(), remaining.begin() + size});
|
||||
}
|
||||
|
||||
void WebGLChild::FlushPendingCmds() {
|
||||
if (!mPendingCmds) return;
|
||||
if (!mPendingCmdsShmem) return;
|
||||
|
||||
const auto cmdBytes = mPendingCmds->mPos;
|
||||
SendDispatchCommands(std::move(mPendingCmds->mShmem), cmdBytes);
|
||||
mPendingCmds = nullptr;
|
||||
const auto byteSize = mPendingCmdsPos;
|
||||
SendDispatchCommands(mPendingCmdsShmem.Extract(), byteSize);
|
||||
|
||||
mFlushedCmdInfo.flushes += 1;
|
||||
mFlushedCmdInfo.flushedCmdBytes += cmdBytes;
|
||||
mFlushedCmdInfo.flushedCmdBytes += byteSize;
|
||||
|
||||
printf_stderr("[WebGLChild] Flushed %zu bytes. (%zu over %zu flushes)\n",
|
||||
byteSize, mFlushedCmdInfo.flushedCmdBytes,
|
||||
mFlushedCmdInfo.flushes);
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
mozilla::ipc::IPCResult WebGLChild::RecvJsWarning(
|
||||
const std::string& text) const {
|
||||
mContext.JsWarning(text);
|
||||
if (!mContext) return IPC_OK();
|
||||
mContext->JsWarning(text);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebGLChild::RecvOnContextLoss(
|
||||
const webgl::ContextLossReason reason) const {
|
||||
mContext.OnContextLoss(reason);
|
||||
if (!mContext) return IPC_OK();
|
||||
mContext->OnContextLoss(reason);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
/* static */
|
||||
IpdlQueueProtocol WebGLChild::GetIpdlQueueProtocol(size_t aCmd, ...) {
|
||||
bool isSync =
|
||||
WebGLMethodDispatcher<>::SyncType(aCmd) == CommandSyncType::SYNC;
|
||||
return isSync ? IpdlQueueProtocol::kSync : IpdlQueueProtocol::kBufferedAsync;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -33,9 +33,10 @@ struct FlushedCmdInfo final {
|
|||
};
|
||||
|
||||
class WebGLChild final : public PWebGLChild,
|
||||
public SupportsWeakPtr<WebGLChild>,
|
||||
public mozilla::webgl::PcqActor {
|
||||
std::unique_ptr<webgl::ShmemCmdBuffer> mPendingCmds;
|
||||
public SupportsWeakPtr<WebGLChild> {
|
||||
const WeakPtr<ClientWebGLContext> mContext;
|
||||
webgl::RaiiShmem mPendingCmdsShmem;
|
||||
size_t mPendingCmdsPos = 0;
|
||||
FlushedCmdInfo mFlushedCmdInfo;
|
||||
|
||||
public:
|
||||
|
@ -43,13 +44,8 @@ class WebGLChild final : public PWebGLChild,
|
|||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGLChild, override);
|
||||
using OtherSideActor = WebGLParent;
|
||||
|
||||
ClientWebGLContext& mContext;
|
||||
|
||||
explicit WebGLChild(ClientWebGLContext&);
|
||||
|
||||
// For SyncProducerActor:
|
||||
static IpdlQueueProtocol GetIpdlQueueProtocol(size_t aCmd, ...);
|
||||
|
||||
Maybe<Range<uint8_t>> AllocPendingCmdBytes(size_t);
|
||||
void FlushPendingCmds();
|
||||
|
||||
|
|
|
@ -26,18 +26,6 @@ using webgl::QueueStatus;
|
|||
|
||||
namespace webgl {
|
||||
|
||||
struct ShmemCmdBuffer final {
|
||||
mozilla::ipc::Shmem mShmem = {};
|
||||
size_t mPos = 0;
|
||||
|
||||
Range<uint8_t> Remaining() const {
|
||||
const auto range = ByteRange(mShmem);
|
||||
return {range.begin() + mPos, range.end()};
|
||||
}
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
class RangeConsumerView final : public webgl::ConsumerView<RangeConsumerView> {
|
||||
RangedPtr<const uint8_t> mSrcItr;
|
||||
const RangedPtr<const uint8_t> mSrcEnd;
|
||||
|
|
|
@ -209,10 +209,6 @@ void WebGLContext::DestroyResourcesAndContext() {
|
|||
|
||||
mIndexedUniformBufferBindings.clear();
|
||||
|
||||
if (mAvailabilityRunnable) {
|
||||
mAvailabilityRunnable->Run();
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
if (mEmptyTFO) {
|
||||
|
@ -1393,48 +1389,6 @@ uint64_t IndexedBufferBinding::ByteCount() const {
|
|||
|
||||
////////////////////////////////////////
|
||||
|
||||
ScopedUnpackReset::ScopedUnpackReset(const WebGLContext* const webgl)
|
||||
: mWebGL(webgl) {
|
||||
const auto& gl = mWebGL->gl;
|
||||
// clang-format off
|
||||
if (mWebGL->mPixelStore.mUnpackAlignment != 4) gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
if (mWebGL->IsWebGL2()) {
|
||||
if (mWebGL->mPixelStore.mUnpackRowLength != 0) gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH , 0);
|
||||
if (mWebGL->mPixelStore.mUnpackImageHeight != 0) gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
if (mWebGL->mPixelStore.mUnpackSkipPixels != 0) gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , 0);
|
||||
if (mWebGL->mPixelStore.mUnpackSkipRows != 0) gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS , 0);
|
||||
if (mWebGL->mPixelStore.mUnpackSkipImages != 0) gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , 0);
|
||||
|
||||
if (mWebGL->mBoundPixelUnpackBuffer) gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
ScopedUnpackReset::~ScopedUnpackReset() {
|
||||
const auto& gl = mWebGL->gl;
|
||||
// clang-format off
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mWebGL->mPixelStore.mUnpackAlignment);
|
||||
|
||||
if (mWebGL->IsWebGL2()) {
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH , mWebGL->mPixelStore.mUnpackRowLength );
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mWebGL->mPixelStore.mUnpackImageHeight);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , mWebGL->mPixelStore.mUnpackSkipPixels );
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS , mWebGL->mPixelStore.mUnpackSkipRows );
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , mWebGL->mPixelStore.mUnpackSkipImages );
|
||||
|
||||
GLuint pbo = 0;
|
||||
if (mWebGL->mBoundPixelUnpackBuffer) {
|
||||
pbo = mWebGL->mBoundPixelUnpackBuffer->mGLName;
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
ScopedFBRebinder::~ScopedFBRebinder() {
|
||||
const auto fnName = [&](WebGLFramebuffer* fb) {
|
||||
return fb ? fb->mGLName : 0;
|
||||
|
@ -1523,54 +1477,6 @@ uint64_t AvailGroups(const uint64_t totalAvailItems,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CheckedUint32 WebGLContext::GetUnpackSize(bool isFunc3D, uint32_t width,
|
||||
uint32_t height, uint32_t depth,
|
||||
uint8_t bytesPerPixel) {
|
||||
if (!width || !height || !depth) return 0;
|
||||
|
||||
////////////////
|
||||
|
||||
const auto& maybeRowLength = mPixelStore.mUnpackRowLength;
|
||||
const auto& maybeImageHeight = mPixelStore.mUnpackImageHeight;
|
||||
|
||||
const auto usedPixelsPerRow =
|
||||
CheckedUint32(mPixelStore.mUnpackSkipPixels) + width;
|
||||
const auto stridePixelsPerRow =
|
||||
(maybeRowLength ? CheckedUint32(maybeRowLength) : usedPixelsPerRow);
|
||||
|
||||
const auto usedRowsPerImage =
|
||||
CheckedUint32(mPixelStore.mUnpackSkipRows) + height;
|
||||
const auto strideRowsPerImage =
|
||||
(maybeImageHeight ? CheckedUint32(maybeImageHeight) : usedRowsPerImage);
|
||||
|
||||
const uint32_t skipImages = (isFunc3D ? mPixelStore.mUnpackSkipImages : 0);
|
||||
const CheckedUint32 usedImages = CheckedUint32(skipImages) + depth;
|
||||
|
||||
////////////////
|
||||
|
||||
CheckedUint32 strideBytesPerRow = bytesPerPixel * stridePixelsPerRow;
|
||||
strideBytesPerRow =
|
||||
RoundUpToMultipleOf(strideBytesPerRow, mPixelStore.mUnpackAlignment);
|
||||
|
||||
const CheckedUint32 strideBytesPerImage =
|
||||
strideBytesPerRow * strideRowsPerImage;
|
||||
|
||||
////////////////
|
||||
|
||||
CheckedUint32 usedBytesPerRow = bytesPerPixel * usedPixelsPerRow;
|
||||
// Don't round this to the alignment, since alignment here is really just used
|
||||
// for establishing stride, particularly in WebGL 1, where you can't set
|
||||
// ROW_LENGTH.
|
||||
|
||||
CheckedUint32 totalBytes = strideBytesPerImage * (usedImages - 1);
|
||||
totalBytes += strideBytesPerRow * (usedRowsPerImage - 1);
|
||||
totalBytes += usedBytesPerRow;
|
||||
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char* WebGLContext::FuncName() const {
|
||||
const char* ret;
|
||||
if (MOZ_LIKELY(mFuncScope)) {
|
||||
|
@ -1642,20 +1548,19 @@ already_AddRefed<dom::Promise> ClientWebGLContext::MakeXRCompatible(
|
|||
|
||||
// --
|
||||
|
||||
webgl::AvailabilityRunnable* WebGLContext::EnsureAvailabilityRunnable() {
|
||||
webgl::AvailabilityRunnable& ClientWebGLContext::EnsureAvailabilityRunnable()
|
||||
const {
|
||||
if (!mAvailabilityRunnable) {
|
||||
RefPtr<webgl::AvailabilityRunnable> runnable =
|
||||
new webgl::AvailabilityRunnable(this);
|
||||
|
||||
NS_DispatchToCurrentThread(runnable.forget());
|
||||
mAvailabilityRunnable = new webgl::AvailabilityRunnable(this);
|
||||
auto forgettable = mAvailabilityRunnable;
|
||||
NS_DispatchToCurrentThread(forgettable.forget());
|
||||
}
|
||||
return mAvailabilityRunnable;
|
||||
return *mAvailabilityRunnable;
|
||||
}
|
||||
|
||||
webgl::AvailabilityRunnable::AvailabilityRunnable(WebGLContext* const webgl)
|
||||
: Runnable("webgl::AvailabilityRunnable"), mWebGL(webgl) {
|
||||
mWebGL->mAvailabilityRunnable = this;
|
||||
}
|
||||
webgl::AvailabilityRunnable::AvailabilityRunnable(
|
||||
const ClientWebGLContext* const webgl)
|
||||
: Runnable("webgl::AvailabilityRunnable"), mWebGL(webgl) {}
|
||||
|
||||
webgl::AvailabilityRunnable::~AvailabilityRunnable() {
|
||||
MOZ_ASSERT(mQueries.empty());
|
||||
|
@ -1664,16 +1569,20 @@ webgl::AvailabilityRunnable::~AvailabilityRunnable() {
|
|||
|
||||
nsresult webgl::AvailabilityRunnable::Run() {
|
||||
for (const auto& cur : mQueries) {
|
||||
if (!cur) continue;
|
||||
cur->mCanBeAvailable = true;
|
||||
}
|
||||
mQueries.clear();
|
||||
|
||||
for (const auto& cur : mSyncs) {
|
||||
if (!cur) continue;
|
||||
cur->mCanBeAvailable = true;
|
||||
}
|
||||
mSyncs.clear();
|
||||
|
||||
mWebGL->mAvailabilityRunnable = nullptr;
|
||||
if (mWebGL) {
|
||||
mWebGL->mAvailabilityRunnable = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ class HostWebGLContext;
|
|||
class ScopedCopyTexImageSource;
|
||||
class ScopedDrawCallWrapper;
|
||||
class ScopedResolveTexturesForDraw;
|
||||
class ScopedUnpackReset;
|
||||
class WebGLBuffer;
|
||||
class WebGLExtensionBase;
|
||||
class WebGLFramebuffer;
|
||||
|
@ -185,11 +184,11 @@ namespace webgl {
|
|||
|
||||
class AvailabilityRunnable final : public Runnable {
|
||||
public:
|
||||
const RefPtr<WebGLContext> mWebGL; // Prevent CC
|
||||
std::vector<RefPtr<WebGLQuery>> mQueries;
|
||||
std::vector<RefPtr<WebGLSync>> mSyncs;
|
||||
const WeakPtr<const ClientWebGLContext> mWebGL;
|
||||
std::vector<WeakPtr<WebGLQueryJS>> mQueries;
|
||||
std::vector<WeakPtr<WebGLSyncJS>> mSyncs;
|
||||
|
||||
explicit AvailabilityRunnable(WebGLContext* webgl);
|
||||
explicit AvailabilityRunnable(const ClientWebGLContext* webgl);
|
||||
~AvailabilityRunnable();
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
@ -393,6 +392,10 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
}
|
||||
void GenerateErrorImpl(const GLenum err, const std::string& text) const;
|
||||
|
||||
void GenerateError(const webgl::ErrorInfo& err) {
|
||||
GenerateError(err.type, "%s", err.info.c_str());
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void GenerateError(const GLenum err, const char* const fmt,
|
||||
const Args&... args) const {
|
||||
|
@ -593,7 +596,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
|
||||
void LineWidth(GLfloat width);
|
||||
void LinkProgram(WebGLProgram& prog);
|
||||
void PixelStorei(GLenum pname, uint32_t param);
|
||||
void PolygonOffset(GLfloat factor, GLfloat units);
|
||||
|
||||
////
|
||||
|
@ -779,10 +781,9 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
const uvec2& size) const;
|
||||
|
||||
// TexSubImage if `!respectFormat`
|
||||
void TexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
|
||||
uvec3 offset, uvec3 size, const webgl::PackingInfo& pi,
|
||||
const TexImageSource& src,
|
||||
const dom::HTMLCanvasElement& canvas) const;
|
||||
void TexImage(uint32_t level, GLenum respecFormat, uvec3 offset,
|
||||
const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlobDesc&) const;
|
||||
|
||||
void TexStorage(GLenum texTarget, uint32_t levels, GLenum sizedFormat,
|
||||
uvec3 size) const;
|
||||
|
@ -1096,7 +1097,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
public:
|
||||
void LoseContext(
|
||||
webgl::ContextLossReason reason = webgl::ContextLossReason::None);
|
||||
const WebGLPixelStore GetPixelStore() const { return mPixelStore; }
|
||||
|
||||
protected:
|
||||
nsTArray<RefPtr<WebGLTexture>> mBound2DTextures;
|
||||
|
@ -1129,20 +1129,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
RefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
|
||||
RefPtr<WebGLVertexArray> mDefaultVertexArray;
|
||||
|
||||
WebGLPixelStore mPixelStore;
|
||||
|
||||
CheckedUint32 GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
|
||||
uint32_t depth, uint8_t bytesPerPixel);
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> FromDomElem(
|
||||
const dom::HTMLCanvasElement& canvas, TexImageTarget target, uvec3 size,
|
||||
const dom::Element& elem, ErrorResult* const out_error) const;
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> From(
|
||||
const dom::HTMLCanvasElement& canvas, TexImageTarget target,
|
||||
const uvec3& size, const TexImageSource& src,
|
||||
dom::Uint8ClampedArray* const scopedArr) const;
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
protected:
|
||||
|
@ -1294,19 +1280,9 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
|
|||
|
||||
const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const;
|
||||
|
||||
// --
|
||||
private:
|
||||
webgl::AvailabilityRunnable* mAvailabilityRunnable = nullptr;
|
||||
|
||||
public:
|
||||
webgl::AvailabilityRunnable* EnsureAvailabilityRunnable();
|
||||
|
||||
// -
|
||||
|
||||
// Friend list
|
||||
friend class ScopedCopyTexImageSource;
|
||||
friend class ScopedResolveTexturesForDraw;
|
||||
friend class ScopedUnpackReset;
|
||||
friend class webgl::TexUnpackBlob;
|
||||
friend class webgl::TexUnpackBytes;
|
||||
friend class webgl::TexUnpackImage;
|
||||
|
@ -1338,15 +1314,6 @@ V RoundUpToMultipleOf(const V& value, const M& multiple) {
|
|||
const char* GetEnumName(GLenum val, const char* defaultRet = "<unknown>");
|
||||
std::string EnumString(GLenum val);
|
||||
|
||||
class ScopedUnpackReset final {
|
||||
private:
|
||||
const WebGLContext* const mWebGL;
|
||||
|
||||
public:
|
||||
explicit ScopedUnpackReset(const WebGLContext* webgl);
|
||||
~ScopedUnpackReset();
|
||||
};
|
||||
|
||||
class ScopedFBRebinder final {
|
||||
private:
|
||||
const WebGLContext* const mWebGL;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
|
@ -738,68 +739,66 @@ void WebGLContext::LinkProgram(WebGLProgram& prog) {
|
|||
}
|
||||
}
|
||||
|
||||
void WebGLContext::PixelStorei(GLenum pname, uint32_t param) {
|
||||
const FuncScope funcScope(*this, "pixelStorei");
|
||||
if (IsContextLost()) return;
|
||||
|
||||
if (IsWebGL2()) {
|
||||
Maybe<webgl::ErrorInfo> SetPixelUnpack(const bool isWebgl2,
|
||||
WebGLPixelStore* const unpacking,
|
||||
const GLenum pname, const GLint param) {
|
||||
if (isWebgl2) {
|
||||
uint32_t* pValueSlot = nullptr;
|
||||
switch (pname) {
|
||||
case LOCAL_GL_UNPACK_IMAGE_HEIGHT:
|
||||
pValueSlot = &mPixelStore.mUnpackImageHeight;
|
||||
pValueSlot = &unpacking->mUnpackImageHeight;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNPACK_SKIP_IMAGES:
|
||||
pValueSlot = &mPixelStore.mUnpackSkipImages;
|
||||
pValueSlot = &unpacking->mUnpackSkipImages;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNPACK_ROW_LENGTH:
|
||||
pValueSlot = &mPixelStore.mUnpackRowLength;
|
||||
pValueSlot = &unpacking->mUnpackRowLength;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNPACK_SKIP_ROWS:
|
||||
pValueSlot = &mPixelStore.mUnpackSkipRows;
|
||||
pValueSlot = &unpacking->mUnpackSkipRows;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNPACK_SKIP_PIXELS:
|
||||
pValueSlot = &mPixelStore.mUnpackSkipPixels;
|
||||
pValueSlot = &unpacking->mUnpackSkipPixels;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pValueSlot) {
|
||||
gl->fPixelStorei(pname, static_cast<int32_t>(param));
|
||||
*pValueSlot = param;
|
||||
return;
|
||||
*pValueSlot = static_cast<uint32_t>(param);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case UNPACK_FLIP_Y_WEBGL:
|
||||
mPixelStore.mFlipY = bool(param);
|
||||
return;
|
||||
case dom::WebGLRenderingContext_Binding::UNPACK_FLIP_Y_WEBGL:
|
||||
unpacking->mFlipY = bool(param);
|
||||
return {};
|
||||
|
||||
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
||||
mPixelStore.mPremultiplyAlpha = bool(param);
|
||||
return;
|
||||
case dom::WebGLRenderingContext_Binding::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
||||
unpacking->mPremultiplyAlpha = bool(param);
|
||||
return {};
|
||||
|
||||
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
|
||||
case dom::WebGLRenderingContext_Binding::UNPACK_COLORSPACE_CONVERSION_WEBGL:
|
||||
switch (param) {
|
||||
case LOCAL_GL_NONE:
|
||||
case BROWSER_DEFAULT_WEBGL:
|
||||
mPixelStore.mColorspaceConversion = param;
|
||||
return;
|
||||
case dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL:
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorInvalidEnumInfo("colorspace conversion parameter", param);
|
||||
return;
|
||||
default: {
|
||||
const nsPrintfCString text("Bad UNPACK_COLORSPACE_CONVERSION: %s",
|
||||
EnumString(param).c_str());
|
||||
return Some(webgl::ErrorInfo{LOCAL_GL_INVALID_VALUE, ToString(text)});
|
||||
}
|
||||
}
|
||||
unpacking->mColorspaceConversion = param;
|
||||
return {};
|
||||
|
||||
case UNPACK_REQUIRE_FASTPATH:
|
||||
if (IsExtensionEnabled(WebGLExtensionID::MOZ_debug)) {
|
||||
mPixelStore.mRequireFastPath = bool(param);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case dom::MOZ_debug_Binding::UNPACK_REQUIRE_FASTPATH:
|
||||
unpacking->mRequireFastPath = bool(param);
|
||||
return {};
|
||||
|
||||
case LOCAL_GL_UNPACK_ALIGNMENT:
|
||||
switch (param) {
|
||||
|
@ -807,20 +806,22 @@ void WebGLContext::PixelStorei(GLenum pname, uint32_t param) {
|
|||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
mPixelStore.mUnpackAlignment = param;
|
||||
gl->fPixelStorei(pname, static_cast<int32_t>(param));
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorInvalidValue("Invalid pack/unpack alignment value.");
|
||||
return;
|
||||
default: {
|
||||
const nsPrintfCString text(
|
||||
"UNPACK_ALIGNMENT must be [1,2,4,8], was %i", param);
|
||||
return Some(webgl::ErrorInfo{LOCAL_GL_INVALID_VALUE, ToString(text)});
|
||||
}
|
||||
}
|
||||
unpacking->mUnpackAlignment = param;
|
||||
return {};
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumInfo("pname", pname);
|
||||
const nsPrintfCString text("Bad `pname`: %s", EnumString(pname).c_str());
|
||||
return Some(webgl::ErrorInfo{LOCAL_GL_INVALID_ENUM, ToString(text)});
|
||||
}
|
||||
|
||||
bool WebGLContext::DoReadPixelsAndConvert(
|
||||
|
|
|
@ -233,8 +233,6 @@ Maybe<double> WebGLContext::GetParameter(const GLenum pname) {
|
|||
}
|
||||
|
||||
case LOCAL_GL_STENCIL_CLEAR_VALUE:
|
||||
case LOCAL_GL_UNPACK_ALIGNMENT:
|
||||
case LOCAL_GL_PACK_ALIGNMENT:
|
||||
case LOCAL_GL_SUBPIXEL_BITS: {
|
||||
GLint i = 0;
|
||||
gl->fGetIntegerv(pname, &i);
|
||||
|
@ -390,16 +388,6 @@ Maybe<double> WebGLContext::GetParameter(const GLenum pname) {
|
|||
return Some(bool(b));
|
||||
}
|
||||
|
||||
// bool, WebGL-specific
|
||||
case UNPACK_FLIP_Y_WEBGL:
|
||||
return Some((bool)mPixelStore.mFlipY);
|
||||
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
||||
return Some((bool)mPixelStore.mPremultiplyAlpha);
|
||||
|
||||
// uint, WebGL-specific
|
||||
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
|
||||
return Some(mPixelStore.mColorspaceConversion);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -145,17 +145,6 @@ void WebGLContext::TexParameter_base(GLenum texTarget, GLenum pname,
|
|||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Uploads
|
||||
|
||||
static bool IsTexTarget3D(const GLenum texTarget) {
|
||||
switch (texTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WebGLTexture* WebGLContext::GetActiveTex(const GLenum texTarget) const {
|
||||
const auto* list = &mBound2DTextures;
|
||||
switch (texTarget) {
|
||||
|
@ -197,25 +186,19 @@ void WebGLContext::TexStorage(GLenum texTarget, uint32_t levels,
|
|||
tex->TexStorage(texTarget, levels, internalFormat, size);
|
||||
}
|
||||
|
||||
void WebGLContext::TexImage(GLenum imageTarget, uint32_t level,
|
||||
GLenum respecFormat, uvec3 offset, uvec3 size,
|
||||
void WebGLContext::TexImage(uint32_t level, GLenum respecFormat, uvec3 offset,
|
||||
const webgl::PackingInfo& pi,
|
||||
const TexImageSource& src,
|
||||
const dom::HTMLCanvasElement& canvas) const {
|
||||
const webgl::TexUnpackBlobDesc& src) const {
|
||||
const WebGLContext::FuncScope funcScope(
|
||||
*this, bool(respecFormat) ? "texImage" : "texSubImage");
|
||||
|
||||
if (respecFormat) {
|
||||
offset = {0, 0, 0};
|
||||
}
|
||||
const auto texTarget = ImageToTexTarget(imageTarget);
|
||||
if (!IsTexTarget3D(texTarget)) {
|
||||
size.z = 1;
|
||||
}
|
||||
const auto texTarget = ImageToTexTarget(src.imageTarget);
|
||||
const auto tex = GetActiveTex(texTarget);
|
||||
if (!tex) return;
|
||||
tex->TexImage(imageTarget, level, respecFormat, offset, size, pi, src,
|
||||
canvas);
|
||||
tex->TexImage(level, respecFormat, offset, pi, src);
|
||||
}
|
||||
|
||||
void WebGLContext::CompressedTexImage(bool sub, GLenum imageTarget,
|
||||
|
|
|
@ -546,22 +546,6 @@ void WebGLContext::AssertCachedGlobalState() const {
|
|||
MOZ_ASSERT(int4[0] == mViewportX && int4[1] == mViewportY &&
|
||||
int4[2] == mViewportWidth && int4[3] == mViewportHeight);
|
||||
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT,
|
||||
mPixelStore.mUnpackAlignment);
|
||||
|
||||
if (IsWebGL2()) {
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_IMAGE_HEIGHT,
|
||||
mPixelStore.mUnpackImageHeight);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_IMAGES,
|
||||
mPixelStore.mUnpackSkipImages);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ROW_LENGTH,
|
||||
mPixelStore.mUnpackRowLength);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_ROWS,
|
||||
mPixelStore.mUnpackSkipRows);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_PIXELS,
|
||||
mPixelStore.mUnpackSkipPixels);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!gl::GLContext::IsBadCallError(errorScope.GetError()));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -575,19 +575,6 @@ bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) {
|
|||
mDefaultVertexArray = WebGLVertexArray::Create(this);
|
||||
mDefaultVertexArray->BindVertexArray();
|
||||
|
||||
mPixelStore.mFlipY = false;
|
||||
mPixelStore.mPremultiplyAlpha = false;
|
||||
mPixelStore.mColorspaceConversion = BROWSER_DEFAULT_WEBGL;
|
||||
mPixelStore.mRequireFastPath = false;
|
||||
|
||||
// GLES 3.0.4, p259:
|
||||
mPixelStore.mUnpackImageHeight = 0;
|
||||
mPixelStore.mUnpackSkipImages = 0;
|
||||
mPixelStore.mUnpackRowLength = 0;
|
||||
mPixelStore.mUnpackSkipRows = 0;
|
||||
mPixelStore.mUnpackSkipPixels = 0;
|
||||
mPixelStore.mUnpackAlignment = 4;
|
||||
|
||||
mPrimRestartTypeBytes = 0;
|
||||
|
||||
mGenericVertexAttribTypes.assign(limits.maxVertexAttribs,
|
||||
|
|
|
@ -10,6 +10,89 @@
|
|||
#include "WebGLTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
// TODO: This should probably replace Shmem, or at least this should move to ipc/glue.
|
||||
class RaiiShmem final {
|
||||
RefPtr<mozilla::ipc::ActorLifecycleProxy> mWeakRef;
|
||||
mozilla::ipc::Shmem mShmem = {};
|
||||
|
||||
public:
|
||||
/// Returns zeroed data.
|
||||
static RaiiShmem Alloc(mozilla::ipc::IProtocol* const allocator,
|
||||
const size_t size,
|
||||
const Shmem::SharedMemory::SharedMemoryType type) {
|
||||
mozilla::ipc::Shmem shmem;
|
||||
if (!allocator->AllocShmem(size, type, &shmem)) return {};
|
||||
return {allocator, shmem};
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
RaiiShmem() = default;
|
||||
|
||||
RaiiShmem(mozilla::ipc::IProtocol* const allocator,
|
||||
const mozilla::ipc::Shmem& shmem)
|
||||
: mWeakRef(allocator->ToplevelProtocol()->GetLifecycleProxy()),
|
||||
mShmem(shmem) {
|
||||
// Shmems are handled by the top-level, so use that or we might leak after
|
||||
// the actor dies.
|
||||
MOZ_ASSERT(mWeakRef);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (IsShmem()) {
|
||||
const auto& allocator = mWeakRef->Get();
|
||||
if (allocator) {
|
||||
allocator->DeallocShmem(mShmem);
|
||||
}
|
||||
}
|
||||
mWeakRef = nullptr;
|
||||
mShmem = {};
|
||||
}
|
||||
|
||||
~RaiiShmem() { reset(); }
|
||||
|
||||
// -
|
||||
|
||||
RaiiShmem(RaiiShmem&& rhs) { *this = std::move(rhs); }
|
||||
RaiiShmem& operator=(RaiiShmem&& rhs) {
|
||||
reset();
|
||||
mWeakRef = rhs.mWeakRef;
|
||||
mShmem = rhs.Extract();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
bool IsShmem() const { return mShmem.IsReadable(); }
|
||||
|
||||
explicit operator bool() const { return IsShmem(); }
|
||||
|
||||
// -
|
||||
|
||||
const auto& Shmem() const {
|
||||
MOZ_ASSERT(IsShmem());
|
||||
return mShmem;
|
||||
}
|
||||
|
||||
Range<uint8_t> ByteRange() const {
|
||||
MOZ_ASSERT(IsShmem());
|
||||
return {mShmem.get<uint8_t>(), mShmem.Size<uint8_t>()};
|
||||
}
|
||||
|
||||
mozilla::ipc::Shmem Extract() {
|
||||
auto ret = mShmem;
|
||||
mShmem = {};
|
||||
reset();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
using Int32Vector = std::vector<int32_t>;
|
||||
|
||||
} // namespace webgl
|
||||
|
||||
namespace ipc {
|
||||
|
||||
template <>
|
||||
|
@ -476,15 +559,4 @@ struct ParamTraits<mozilla::avec3<U>> final {
|
|||
|
||||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
using MaybeDouble = Maybe<double>;
|
||||
using MaybeFrontBufferSnapshotIpc = Maybe<FrontBufferSnapshotIpc>;
|
||||
using MaybeSurfaceDescriptor = Maybe<layers::SurfaceDescriptor>;
|
||||
using MaybeReadPixelsResultIpc = Maybe<ReadPixelsResultIpc>;
|
||||
using MaybeShaderPrecisionFormat = Maybe<ShaderPrecisionFormat>;
|
||||
using MaybeString = Maybe<std::string>;
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
|
@ -113,7 +113,6 @@ DEFINE_ASYNC(HostWebGLContext::FrontFace)
|
|||
DEFINE_ASYNC(HostWebGLContext::Hint)
|
||||
DEFINE_ASYNC(HostWebGLContext::LineWidth)
|
||||
DEFINE_ASYNC(HostWebGLContext::LinkProgram)
|
||||
DEFINE_ASYNC(HostWebGLContext::PixelStorei)
|
||||
DEFINE_ASYNC(HostWebGLContext::PolygonOffset)
|
||||
DEFINE_ASYNC(HostWebGLContext::Present)
|
||||
DEFINE_ASYNC(HostWebGLContext::SampleCoverage)
|
||||
|
@ -140,7 +139,7 @@ DEFINE_ASYNC(HostWebGLContext::BindTexture)
|
|||
DEFINE_ASYNC(HostWebGLContext::GenerateMipmap)
|
||||
DEFINE_ASYNC(HostWebGLContext::CopyTexImage)
|
||||
DEFINE_ASYNC(HostWebGLContext::TexStorage)
|
||||
// DEFINE_ASYNC(HostWebGLContext::TexImage)
|
||||
DEFINE_ASYNC(HostWebGLContext::TexImage)
|
||||
DEFINE_ASYNC(HostWebGLContext::CompressedTexImage)
|
||||
// DEFINE_SYNC(HostWebGLContext::GetTexParameter)
|
||||
DEFINE_ASYNC(HostWebGLContext::TexParameter_base)
|
||||
|
|
|
@ -39,17 +39,19 @@ mozilla::ipc::IPCResult WebGLParent::RecvInitialize(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
WebGLParent::WebGLParent() : PcqActor(this) {}
|
||||
WebGLParent::WebGLParent() = default;
|
||||
WebGLParent::~WebGLParent() = default;
|
||||
|
||||
// -
|
||||
|
||||
using IPCResult = mozilla::ipc::IPCResult;
|
||||
|
||||
IPCResult WebGLParent::RecvDispatchCommands(Shmem&& shmem,
|
||||
IPCResult WebGLParent::RecvDispatchCommands(Shmem&& rawShmem,
|
||||
const uint64_t cmdsByteSize) {
|
||||
auto shmem = webgl::RaiiShmem(this, std::move(rawShmem));
|
||||
|
||||
MOZ_ASSERT(cmdsByteSize);
|
||||
const auto shmemBytes = ByteRange(shmem);
|
||||
const auto shmemBytes = shmem.ByteRange();
|
||||
const auto byteSize = std::min<uint64_t>(shmemBytes.length(), cmdsByteSize);
|
||||
const auto cmdsBytes =
|
||||
Range<const uint8_t>{shmemBytes.begin(), shmemBytes.begin() + byteSize};
|
||||
|
@ -84,16 +86,19 @@ IPCResult WebGLParent::RecvGetFrontBufferSnapshot(
|
|||
const auto surfSize = mHost->GetFrontBufferSize();
|
||||
const auto byteSize = 4 * surfSize.x * surfSize.y;
|
||||
|
||||
Shmem shmem;
|
||||
if (!PWebGLParent::AllocShmem(
|
||||
byteSize, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
|
||||
&shmem)) {
|
||||
auto shmem = webgl::RaiiShmem::Alloc(
|
||||
this, byteSize, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC);
|
||||
MOZ_ASSERT(shmem);
|
||||
if (!shmem) {
|
||||
return IPC_FAIL(this, "Failed to allocate shmem for result");
|
||||
}
|
||||
|
||||
auto shmemBytes = ByteRange(shmem);
|
||||
if (!mHost->FrontBufferSnapshotInto(shmemBytes)) return IPC_OK();
|
||||
*ret = {surfSize, Some(std::move(shmem))};
|
||||
const auto range = shmem.ByteRange();
|
||||
auto retSize = surfSize;
|
||||
if (!mHost->FrontBufferSnapshotInto(range)) {
|
||||
retSize = {0, 0}; // Zero means failure.
|
||||
}
|
||||
*ret = {retSize, shmem.Extract()};
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -101,43 +106,45 @@ IPCResult WebGLParent::RecvGetBufferSubData(const GLenum target,
|
|||
const uint64_t srcByteOffset,
|
||||
const uint64_t byteSize,
|
||||
Shmem* const ret) {
|
||||
Shmem shmem;
|
||||
if (!PWebGLParent::AllocShmem(
|
||||
byteSize, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
|
||||
&shmem)) {
|
||||
MOZ_ASSERT(false);
|
||||
const auto allocSize = 1 + byteSize;
|
||||
auto shmem = webgl::RaiiShmem::Alloc(
|
||||
this, allocSize,
|
||||
mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC);
|
||||
MOZ_ASSERT(shmem);
|
||||
if (!shmem) {
|
||||
return IPC_FAIL(this, "Failed to allocate shmem for result");
|
||||
}
|
||||
|
||||
const auto range = ByteRange(shmem);
|
||||
memset(range.begin().get(), 0,
|
||||
range.length()); // TODO: This is usually overkill.
|
||||
const auto shmemRange = shmem.ByteRange();
|
||||
const auto dataRange =
|
||||
Range<uint8_t>{shmemRange.begin() + 1, shmemRange.end()};
|
||||
|
||||
if (mHost->GetBufferSubData(target, srcByteOffset, range)) {
|
||||
*ret = std::move(shmem);
|
||||
}
|
||||
// We need to always send the shmem:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1463831#c2
|
||||
const auto ok = mHost->GetBufferSubData(target, srcByteOffset, dataRange);
|
||||
*(shmemRange.begin().get()) = ok;
|
||||
*ret = shmem.Extract();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult WebGLParent::RecvReadPixels(const webgl::ReadPixelsDesc& desc,
|
||||
const uint64_t byteCount,
|
||||
const uint64_t byteSize,
|
||||
webgl::ReadPixelsResultIpc* const ret) {
|
||||
*ret = {};
|
||||
|
||||
Shmem shmem;
|
||||
if (!PWebGLParent::AllocShmem(
|
||||
byteCount, mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC,
|
||||
&shmem)) {
|
||||
MOZ_ASSERT(false);
|
||||
const auto allocSize = std::max<uint64_t>(1, byteSize);
|
||||
auto shmem = webgl::RaiiShmem::Alloc(
|
||||
this, allocSize,
|
||||
mozilla::ipc::SharedMemory::SharedMemoryType::TYPE_BASIC);
|
||||
MOZ_ASSERT(shmem);
|
||||
if (!shmem) {
|
||||
return IPC_FAIL(this, "Failed to allocate shmem for result");
|
||||
}
|
||||
|
||||
auto range = ByteRange(shmem);
|
||||
memset(range.begin().get(), 0,
|
||||
range.length()); // TODO: This is usually overkill.
|
||||
const auto range = shmem.ByteRange();
|
||||
|
||||
const auto res = mHost->ReadPixelsInto(desc, range);
|
||||
*ret = {res, std::move(shmem)};
|
||||
*ret = {res, shmem.Extract()};
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@ class SurfaceDescriptor;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class WebGLParent : public PWebGLParent,
|
||||
public SupportsWeakPtr<WebGLParent>,
|
||||
public mozilla::webgl::PcqActor {
|
||||
class WebGLParent : public PWebGLParent, public SupportsWeakPtr<WebGLParent> {
|
||||
friend PWebGLParent;
|
||||
|
||||
public:
|
||||
|
@ -42,6 +40,8 @@ class WebGLParent : public PWebGLParent,
|
|||
|
||||
IPCResult RecvDispatchCommands(mozilla::ipc::Shmem&&, uint64_t);
|
||||
|
||||
IPCResult RecvGetBufferSubData(GLenum target, uint64_t srcByteOffset,
|
||||
uint64_t byteSize, mozilla::ipc::Shmem* ret);
|
||||
IPCResult RecvGetFrontBufferSnapshot(webgl::FrontBufferSnapshotIpc* ret);
|
||||
IPCResult RecvReadPixels(const webgl::ReadPixelsDesc&, uint64_t byteSize,
|
||||
webgl::ReadPixelsResultIpc* ret);
|
||||
|
@ -60,8 +60,6 @@ class WebGLParent : public PWebGLParent,
|
|||
IPCResult RecvFinish();
|
||||
IPCResult RecvGetBufferParameter(GLenum target, GLenum pname,
|
||||
Maybe<double>* ret);
|
||||
IPCResult RecvGetBufferSubData(GLenum target, uint64_t srcByteOffset,
|
||||
uint64_t byteSize, mozilla::ipc::Shmem* ret);
|
||||
IPCResult RecvGetCompileResult(ObjectId id, webgl::CompileResult* ret);
|
||||
IPCResult RecvGetError(GLenum* ret);
|
||||
IPCResult RecvGetFragDataLocation(ObjectId id, const std::string& name,
|
||||
|
|
|
@ -76,11 +76,6 @@ void WebGLQuery::EndQuery() {
|
|||
|
||||
const auto driverTarget = TargetForDriver(gl, mTarget);
|
||||
gl->fEndQuery(driverTarget);
|
||||
|
||||
////
|
||||
|
||||
const auto& availRunnable = mContext->EnsureAvailabilityRunnable();
|
||||
availRunnable->mQueries.push_back(this);
|
||||
}
|
||||
|
||||
Maybe<double> WebGLQuery::GetQueryParameter(GLenum pname) const {
|
||||
|
@ -107,16 +102,6 @@ Maybe<double> WebGLQuery::GetQueryParameter(GLenum pname) const {
|
|||
// End of validation
|
||||
////
|
||||
|
||||
// We must usually wait for an event loop before the query can be available.
|
||||
const bool canBeAvailable =
|
||||
(mCanBeAvailable || StaticPrefs::webgl_allow_immediate_queries());
|
||||
if (!canBeAvailable) {
|
||||
if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
|
||||
return Some(false);
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
const auto& gl = mContext->gl;
|
||||
|
||||
uint64_t val = 0;
|
||||
|
@ -167,9 +152,6 @@ void WebGLQuery::QueryCounter() {
|
|||
|
||||
const auto& gl = mContext->gl;
|
||||
gl->fQueryCounter(mGLName, mTarget);
|
||||
|
||||
const auto& availRunnable = mContext->EnsureAvailabilityRunnable();
|
||||
availRunnable->mQueries.push_back(this);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -43,6 +43,9 @@ struct IsTriviallySerializable<webgl::ExtensionBits> : std::true_type {};
|
|||
template <>
|
||||
struct IsTriviallySerializable<webgl::GetUniformData> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct IsTriviallySerializable<mozilla::webgl::PackingInfo> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct IsTriviallySerializable<ICRData> : std::true_type {};
|
||||
|
||||
|
@ -202,7 +205,6 @@ struct QueueParamTraits<std::vector<U>> {
|
|||
|
||||
template <typename V>
|
||||
static QueueStatus Read(ConsumerView<V>& aConsumerView, T* aArg) {
|
||||
MOZ_CRASH("no way to fallibly resize vectors without exceptions");
|
||||
size_t size;
|
||||
auto status = aConsumerView.ReadParam(&size);
|
||||
if (!status) return status;
|
||||
|
|
|
@ -586,9 +586,11 @@ static bool ZeroTextureData(const WebGLContext* webgl, GLuint tex,
|
|||
UniqueBuffer zeros = calloc(1u, sliceByteCount);
|
||||
if (!zeros) return false;
|
||||
|
||||
ScopedUnpackReset scopedReset(webgl);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with
|
||||
// striding it well.
|
||||
// Don't bother with striding it well.
|
||||
// TODO: We shouldn't need to do this for CompressedTexSubImage.
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
|
||||
const auto revert = MakeScopeExit(
|
||||
[&]() { gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); });
|
||||
|
||||
GLenum error = 0;
|
||||
for (const auto z : IntegerRange(depth)) {
|
||||
|
@ -628,9 +630,10 @@ static bool ZeroTextureData(const WebGLContext* webgl, GLuint tex,
|
|||
UniqueBuffer zeros = calloc(1u, sliceByteCount);
|
||||
if (!zeros) return false;
|
||||
|
||||
ScopedUnpackReset scopedReset(webgl);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
|
||||
1); // Don't bother with striding it well.
|
||||
// Don't bother with striding it well.
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
|
||||
const auto revert =
|
||||
MakeScopeExit([&]() { gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); });
|
||||
|
||||
GLenum error = 0;
|
||||
for (const auto z : IntegerRange(depth)) {
|
||||
|
|
|
@ -201,10 +201,8 @@ class WebGLTexture final : public WebGLContextBoundObject,
|
|||
const uvec3& size);
|
||||
|
||||
// TexSubImage iff `!respecFormat`
|
||||
void TexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
|
||||
const uvec3& offset, const uvec3& size,
|
||||
const webgl::PackingInfo& pi, const TexImageSource& src,
|
||||
const dom::HTMLCanvasElement& canvas);
|
||||
void TexImage(uint32_t level, GLenum respecFormat, const uvec3& offset,
|
||||
const webgl::PackingInfo& pi, const webgl::TexUnpackBlobDesc&);
|
||||
|
||||
// CompressedTexSubImage iff `sub`
|
||||
void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <limits>
|
||||
|
||||
#include "CanvasUtils.h"
|
||||
#include "ClientWebGLContext.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/Casting.h"
|
||||
|
@ -30,63 +31,19 @@
|
|||
#include "WebGLTexelConversions.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBytes> FromView(
|
||||
const WebGLContext* webgl, TexImageTarget target, const uvec3& size,
|
||||
const dom::ArrayBufferView* view, GLuint viewElemOffset,
|
||||
GLuint viewElemLengthOverride) {
|
||||
const bool isClientData = true;
|
||||
const uint8_t* bytes = nullptr;
|
||||
size_t availByteCount = 0;
|
||||
if (view) {
|
||||
const auto range =
|
||||
GetRangeFromView(*view, viewElemOffset, viewElemLengthOverride);
|
||||
if (!range) {
|
||||
webgl->GenerateError(LOCAL_GL_INVALID_OPERATION, "`source` too small.");
|
||||
return nullptr;
|
||||
}
|
||||
bytes = range->begin().get();
|
||||
availByteCount = range->length();
|
||||
}
|
||||
return MakeUnique<webgl::TexUnpackBytes>(webgl, target, size.x, size.y,
|
||||
size.z, isClientData, bytes,
|
||||
availByteCount);
|
||||
}
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBytes> FromPboOffset(const WebGLContext* webgl,
|
||||
TexImageTarget target,
|
||||
const uvec3& size,
|
||||
WebGLintptr pboOffset) {
|
||||
if (!webgl->ValidateNonNegative("offset", pboOffset)) return nullptr;
|
||||
|
||||
const auto& buffer =
|
||||
webgl->ValidateBufferSelection(LOCAL_GL_PIXEL_UNPACK_BUFFER);
|
||||
if (!buffer) return nullptr;
|
||||
|
||||
size_t availBufferBytes = buffer->ByteLength();
|
||||
if (size_t(pboOffset) > availBufferBytes) {
|
||||
webgl->ErrorInvalidOperation("Offset is passed end of buffer.");
|
||||
return nullptr;
|
||||
}
|
||||
availBufferBytes -= pboOffset;
|
||||
const bool isClientData = false;
|
||||
const auto ptr = (const uint8_t*)pboOffset;
|
||||
return MakeUnique<webgl::TexUnpackBytes>(webgl, target, size.x, size.y,
|
||||
size.z, isClientData, ptr,
|
||||
availBufferBytes);
|
||||
}
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBlob> FromImageBitmap(
|
||||
const WebGLContext* webgl, TexImageTarget target, uvec3 size,
|
||||
const dom::ImageBitmap& imageBitmap, ErrorResult* aRv) {
|
||||
Maybe<TexUnpackBlobDesc> FromImageBitmap(const GLenum target, uvec3 size,
|
||||
const dom::ImageBitmap& imageBitmap,
|
||||
ErrorResult* const out_rv) {
|
||||
if (imageBitmap.IsWriteOnly()) {
|
||||
aRv->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
out_rv->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return {};
|
||||
}
|
||||
|
||||
UniquePtr<dom::ImageBitmapCloneData> cloneData = imageBitmap.ToCloneData();
|
||||
const auto cloneData = imageBitmap.ToCloneData();
|
||||
if (!cloneData) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
const RefPtr<gfx::DataSourceSurface> surf = cloneData->mSurface;
|
||||
|
@ -102,40 +59,27 @@ static UniquePtr<webgl::TexUnpackBlob> FromImageBitmap(
|
|||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
return MakeUnique<webgl::TexUnpackSurface>(
|
||||
webgl, target, size.x, size.y, size.z, surf, cloneData->mAlphaType);
|
||||
return Some(
|
||||
TexUnpackBlobDesc{target, size, cloneData->mAlphaType, {}, {}, {}, surf});
|
||||
}
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBlob> FromImageData(
|
||||
const WebGLContext* webgl, TexImageTarget target, uvec3 size,
|
||||
const dom::ImageData& imageData, dom::Uint8ClampedArray* scopedArr) {
|
||||
DebugOnly<bool> inited = scopedArr->Init(imageData.GetDataObject());
|
||||
MOZ_ASSERT(inited);
|
||||
|
||||
TexUnpackBlobDesc FromImageData(const GLenum target, uvec3 size,
|
||||
const dom::ImageData& imageData,
|
||||
dom::Uint8ClampedArray* const scopedArr) {
|
||||
MOZ_RELEASE_ASSERT(scopedArr->Init(imageData.GetDataObject()));
|
||||
scopedArr->ComputeState();
|
||||
const DebugOnly<size_t> dataSize = scopedArr->Length();
|
||||
const void* const data = scopedArr->Data();
|
||||
const size_t dataSize = scopedArr->Length();
|
||||
const auto data = reinterpret_cast<uint8_t*>(scopedArr->Data());
|
||||
|
||||
const gfx::IntSize imageSize(imageData.Width(), imageData.Height());
|
||||
const size_t stride = imageSize.width * 4;
|
||||
const gfx::SurfaceFormat surfFormat = gfx::SurfaceFormat::R8G8B8A8;
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
const auto alphaType = gfxAlphaType::NonPremult;
|
||||
|
||||
MOZ_ASSERT(dataSize == stride * imageSize.height);
|
||||
|
||||
uint8_t* wrappableData = (uint8_t*)data;
|
||||
MOZ_ALWAYS_TRUE(dataSize == stride * imageSize.height);
|
||||
|
||||
const RefPtr<gfx::DataSourceSurface> surf =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(wrappableData, stride,
|
||||
imageSize, surfFormat);
|
||||
if (!surf) {
|
||||
webgl->ErrorOutOfMemory("OOM in FromImageData.");
|
||||
return nullptr;
|
||||
}
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(data, stride, imageSize,
|
||||
surfFormat);
|
||||
MOZ_ASSERT(surf);
|
||||
|
||||
////
|
||||
|
||||
|
@ -149,19 +93,25 @@ static UniquePtr<webgl::TexUnpackBlob> FromImageData(
|
|||
|
||||
////
|
||||
|
||||
return MakeUnique<webgl::TexUnpackSurface>(webgl, target, size.x, size.y,
|
||||
size.z, surf, alphaType);
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
return {target, size, gfxAlphaType::NonPremult, {}, {}, {}, surf};
|
||||
}
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(
|
||||
const dom::HTMLCanvasElement& canvas, TexImageTarget target, uvec3 size,
|
||||
const dom::Element& elem, ErrorResult* const out_error) const {
|
||||
Maybe<webgl::TexUnpackBlobDesc> FromDomElem(const ClientWebGLContext& webgl,
|
||||
const GLenum target, uvec3 size,
|
||||
const dom::Element& elem,
|
||||
const bool allowBlitImage,
|
||||
ErrorResult* const out_error) {
|
||||
const auto& canvas = *webgl.GetCanvas();
|
||||
|
||||
if (elem.IsHTMLElement(nsGkAtoms::canvas)) {
|
||||
const dom::HTMLCanvasElement* canvas =
|
||||
const dom::HTMLCanvasElement* srcCanvas =
|
||||
static_cast<const dom::HTMLCanvasElement*>(&elem);
|
||||
if (canvas->IsWriteOnly()) {
|
||||
if (srcCanvas->IsWriteOnly()) {
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,9 +122,10 @@ UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(
|
|||
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
|
||||
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR |
|
||||
nsLayoutUtils::SFE_ALLOW_NON_PREMULT;
|
||||
|
||||
if (mPixelStore.mColorspaceConversion == LOCAL_GL_NONE)
|
||||
const auto& unpacking = webgl.State().mPixelUnpackState;
|
||||
if (unpacking.mColorspaceConversion == LOCAL_GL_NONE) {
|
||||
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DrawTarget> idealDrawTarget = nullptr; // Don't care for now.
|
||||
auto sfer = nsLayoutUtils::SurfaceFromElement(
|
||||
|
@ -185,7 +136,8 @@ UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(
|
|||
uint32_t elemWidth = 0;
|
||||
uint32_t elemHeight = 0;
|
||||
layers::Image* layersImage = nullptr;
|
||||
if (!StaticPrefs::webgl_disable_DOM_blit_uploads() && sfer.mLayersImage) {
|
||||
|
||||
if (sfer.mLayersImage && allowBlitImage) {
|
||||
layersImage = sfer.mLayersImage;
|
||||
elemWidth = layersImage->GetSize().width;
|
||||
elemHeight = layersImage->GetSize().height;
|
||||
|
@ -214,9 +166,7 @@ UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(
|
|||
////
|
||||
|
||||
if (!layersImage && !dataSurf) {
|
||||
const bool isClientData = true;
|
||||
return MakeUnique<webgl::TexUnpackBytes>(this, target, size.x, size.y,
|
||||
size.z, isClientData, nullptr, 0);
|
||||
return Some(TexUnpackBlobDesc{target, size, gfxAlphaType::NonPremult});
|
||||
}
|
||||
|
||||
//////
|
||||
|
@ -230,9 +180,9 @@ UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(
|
|||
nsIPrincipal* dstPrincipal = canvas.NodePrincipal();
|
||||
|
||||
if (!dstPrincipal->Subsumes(srcPrincipal)) {
|
||||
GenerateWarning("Cross-origin elements require CORS.");
|
||||
webgl.EnqueueWarning("Cross-origin elements require CORS.");
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,55 +190,25 @@ UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(
|
|||
// mIsWriteOnly defaults to true, and so will be true even if SFE merely
|
||||
// failed. Thus we must test mIsWriteOnly after successfully retrieving an
|
||||
// Image or SourceSurface.
|
||||
GenerateWarning("Element is write-only, thus cannot be uploaded.");
|
||||
webgl.EnqueueWarning("Element is write-only, thus cannot be uploaded.");
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
//////
|
||||
// Ok, we're good!
|
||||
|
||||
if (layersImage) {
|
||||
return MakeUnique<webgl::TexUnpackImage>(
|
||||
this, target, size.x, size.y, size.z, layersImage, sfer.mAlphaType);
|
||||
return Some(
|
||||
TexUnpackBlobDesc{target, size, sfer.mAlphaType, {}, {}, layersImage});
|
||||
}
|
||||
|
||||
MOZ_ASSERT(dataSurf);
|
||||
return MakeUnique<webgl::TexUnpackSurface>(this, target, size.x, size.y,
|
||||
size.z, dataSurf, sfer.mAlphaType);
|
||||
return Some(
|
||||
TexUnpackBlobDesc{target, size, sfer.mAlphaType, {}, {}, {}, dataSurf});
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> WebGLContext::From(
|
||||
const dom::HTMLCanvasElement& canvas, TexImageTarget target,
|
||||
const uvec3& size, const TexImageSource& src,
|
||||
dom::Uint8ClampedArray* const scopedArr) const {
|
||||
if (src.mPboOffset) {
|
||||
return FromPboOffset(this, target, size, *(src.mPboOffset));
|
||||
}
|
||||
|
||||
if (mBoundPixelUnpackBuffer) {
|
||||
ErrorInvalidOperation("PIXEL_UNPACK_BUFFER must be null.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (src.mImageBitmap) {
|
||||
return FromImageBitmap(this, target, size, *(src.mImageBitmap),
|
||||
src.mOut_error);
|
||||
}
|
||||
|
||||
if (src.mImageData) {
|
||||
return FromImageData(this, target, size, *(src.mImageData), scopedArr);
|
||||
}
|
||||
|
||||
if (src.mDomElem) {
|
||||
return FromDomElem(canvas, target, size, *(src.mDomElem), src.mOut_error);
|
||||
}
|
||||
|
||||
return FromView(this, target, size, src.mView, src.mViewElemOffset,
|
||||
src.mViewElemLengthOverride);
|
||||
}
|
||||
} // namespace webgl
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -936,21 +856,28 @@ void WebGLTexture::TexStorage(TexTarget target, uint32_t levels,
|
|||
// Tex(Sub)Image
|
||||
|
||||
// TexSubImage iff `!respectFormat`
|
||||
void WebGLTexture::TexImage(GLenum imageTarget, uint32_t level,
|
||||
GLenum respecFormat, const uvec3& offset,
|
||||
const uvec3& claimedSize,
|
||||
const webgl::PackingInfo& pi,
|
||||
const TexImageSource& src,
|
||||
const dom::HTMLCanvasElement& canvas) {
|
||||
dom::Uint8ClampedArray scopedArr;
|
||||
const auto blob =
|
||||
mContext->From(canvas, imageTarget, claimedSize, src, &scopedArr);
|
||||
if (!blob) return;
|
||||
void WebGLTexture::TexImage(uint32_t level, GLenum respecFormat,
|
||||
const uvec3& offset, const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlobDesc& src) {
|
||||
Maybe<RawBuffer<>> cpuDataView;
|
||||
if (src.cpuData) {
|
||||
cpuDataView = Some(RawBuffer<>{src.cpuData->Data()});
|
||||
}
|
||||
const auto srcViewDesc = webgl::TexUnpackBlobDesc{
|
||||
src.imageTarget, src.size, src.srcAlphaType, std::move(cpuDataView),
|
||||
src.pboOffset, src.image, src.surf, src.unpacking};
|
||||
const auto blob = webgl::TexUnpackBlob::Create(srcViewDesc);
|
||||
if (!blob) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// For DOM element upload entrypoints that have no size arguments, claimedSize
|
||||
// is 0. Use blob size, not claimedSize. (blob size can also be zero, and
|
||||
// that's valid!)
|
||||
const auto size = uvec3{blob->mWidth, blob->mHeight, blob->mDepth};
|
||||
const auto imageTarget = blob->mDesc.imageTarget;
|
||||
auto size = blob->mDesc.size;
|
||||
|
||||
if (!IsTarget3D(imageTarget)) {
|
||||
size.z = 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
|
@ -1055,6 +982,12 @@ void WebGLTexture::TexImage(GLenum imageTarget, uint32_t level,
|
|||
////////////////////////////////////
|
||||
// Do the thing!
|
||||
|
||||
blob->mDesc.unpacking.Apply(*mContext->gl, mContext->IsWebGL2(), size);
|
||||
const auto revertUnpacking = MakeScopeExit([&]() {
|
||||
const WebGLPixelStore defaultUnpacking;
|
||||
defaultUnpacking.Apply(*mContext->gl, mContext->IsWebGL2(), size);
|
||||
});
|
||||
|
||||
Maybe<webgl::ImageInfo> newImageInfo;
|
||||
bool isRespec = false;
|
||||
if (respecFormat) {
|
||||
|
@ -1063,7 +996,7 @@ void WebGLTexture::TexImage(GLenum imageTarget, uint32_t level,
|
|||
newImageInfo = Some(webgl::ImageInfo{dstUsage, size.x, size.y, size.z});
|
||||
if (!blob->HasData()) {
|
||||
newImageInfo->mUninitializedSlices =
|
||||
Some(std::vector<bool>(blob->mDepth, true));
|
||||
Some(std::vector<bool>(size.z, true));
|
||||
}
|
||||
|
||||
isRespec = (imageInfo->mWidth != newImageInfo->mWidth ||
|
||||
|
@ -1083,9 +1016,8 @@ void WebGLTexture::TexImage(GLenum imageTarget, uint32_t level,
|
|||
|
||||
const bool isSubImage = !respecFormat;
|
||||
GLenum glError;
|
||||
if (!blob->TexOrSubImage(isSubImage, isRespec, this, imageTarget, level,
|
||||
driverUnpackInfo, offset.x, offset.y, offset.z, pi,
|
||||
&glError)) {
|
||||
if (!blob->TexOrSubImage(isSubImage, isRespec, this, level, driverUnpackInfo,
|
||||
offset.x, offset.y, offset.z, pi, &glError)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1702,8 +1634,9 @@ static bool DoCopyTexOrSubImage(WebGLContext* webgl, bool isSubImage,
|
|||
}
|
||||
|
||||
if (!isSubImage || zeros) {
|
||||
const ScopedUnpackReset unpackReset(webgl);
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
|
||||
const auto revert = MakeScopeExit(
|
||||
[&]() { gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); });
|
||||
if (!isSubImage) {
|
||||
error = DoTexImage(gl, target, level, idealUnpack, dstWidth, dstHeight,
|
||||
1, nullptr);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "nsString.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "mozilla/ipc/SharedMemoryBasic.h"
|
||||
//#include "WebGLStrongTypes.h"
|
||||
|
||||
// Manual reflection of WebIDL typedefs that are different from their
|
||||
// OpenGL counterparts.
|
||||
|
@ -289,9 +288,9 @@ class UniqueBuffer {
|
|||
|
||||
void* get() const { return mBuffer; }
|
||||
|
||||
UniqueBuffer(const UniqueBuffer& other) =
|
||||
explicit UniqueBuffer(const UniqueBuffer& other) =
|
||||
delete; // construct using std::move()!
|
||||
void operator=(const UniqueBuffer& other) =
|
||||
UniqueBuffer& operator=(const UniqueBuffer& other) =
|
||||
delete; // assign using std::move()!
|
||||
};
|
||||
|
||||
|
@ -351,19 +350,6 @@ struct FloatOrInt final // For TexParameter[fi] and friends.
|
|||
}
|
||||
};
|
||||
|
||||
struct WebGLPixelStore final {
|
||||
uint32_t mUnpackImageHeight = 0;
|
||||
uint32_t mUnpackSkipImages = 0;
|
||||
uint32_t mUnpackRowLength = 0;
|
||||
uint32_t mUnpackSkipRows = 0;
|
||||
uint32_t mUnpackSkipPixels = 0;
|
||||
uint32_t mUnpackAlignment = 0;
|
||||
GLenum mColorspaceConversion = 0;
|
||||
bool mFlipY = false;
|
||||
bool mPremultiplyAlpha = false;
|
||||
bool mRequireFastPath = false;
|
||||
};
|
||||
|
||||
using WebGLTexUnpackVariant =
|
||||
Variant<UniquePtr<webgl::TexUnpackBytes>,
|
||||
UniquePtr<webgl::TexUnpackSurface>,
|
||||
|
@ -692,7 +678,7 @@ struct GetUniformData final {
|
|||
|
||||
struct FrontBufferSnapshotIpc final {
|
||||
uvec2 surfSize = {};
|
||||
Maybe<mozilla::ipc::Shmem> shmem;
|
||||
mozilla::ipc::Shmem shmem = {};
|
||||
};
|
||||
|
||||
struct ReadPixelsResult {
|
||||
|
@ -733,7 +719,7 @@ struct ICRData {
|
|||
* inner data type must be trivially copyable by memcpy.
|
||||
*/
|
||||
template <typename T = uint8_t>
|
||||
class RawBuffer {
|
||||
class RawBuffer final {
|
||||
const T* mBegin = nullptr;
|
||||
size_t mLen = 0;
|
||||
UniqueBuffer mOwned;
|
||||
|
@ -752,6 +738,7 @@ class RawBuffer {
|
|||
~RawBuffer() = default;
|
||||
|
||||
Range<const T> Data() const { return {mBegin, mLen}; }
|
||||
const auto& begin() const { return mBegin; };
|
||||
|
||||
RawBuffer() = default;
|
||||
|
||||
|
@ -870,6 +857,17 @@ inline GLenum ImageToTexTarget(const GLenum imageTarget) {
|
|||
}
|
||||
}
|
||||
|
||||
inline bool IsTexTarget3D(const GLenum texTarget) {
|
||||
switch (texTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
namespace dom {
|
||||
|
@ -892,15 +890,77 @@ struct TexImageSource {
|
|||
ErrorResult* mOut_error = nullptr;
|
||||
};
|
||||
|
||||
struct WebGLPixelStore final {
|
||||
uint32_t mUnpackImageHeight = 0;
|
||||
uint32_t mUnpackSkipImages = 0;
|
||||
uint32_t mUnpackRowLength = 0;
|
||||
uint32_t mUnpackSkipRows = 0;
|
||||
uint32_t mUnpackSkipPixels = 0;
|
||||
uint32_t mUnpackAlignment = 4;
|
||||
GLenum mColorspaceConversion =
|
||||
dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL;
|
||||
bool mFlipY = false;
|
||||
bool mPremultiplyAlpha = false;
|
||||
bool mRequireFastPath = false;
|
||||
|
||||
void Apply(gl::GLContext&, bool isWebgl2, const uvec3& uploadSize) const;
|
||||
|
||||
WebGLPixelStore ForUseWith(
|
||||
const GLenum target, const uvec3& uploadSize,
|
||||
const Maybe<gfx::IntSize>& structuredSrcSize) const {
|
||||
auto ret = *this;
|
||||
|
||||
if (!IsTexTarget3D(target)) {
|
||||
ret.mUnpackSkipImages = 0;
|
||||
ret.mUnpackImageHeight = 0;
|
||||
}
|
||||
|
||||
if (structuredSrcSize) {
|
||||
ret.mUnpackRowLength = structuredSrcSize->width;
|
||||
}
|
||||
|
||||
if (!ret.mUnpackRowLength) {
|
||||
ret.mUnpackRowLength = uploadSize.x;
|
||||
}
|
||||
if (!ret.mUnpackImageHeight) {
|
||||
ret.mUnpackImageHeight = uploadSize.y;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct TexImageData final {
|
||||
WebGLPixelStore unpackState;
|
||||
|
||||
Maybe<uint64_t> pboOffset;
|
||||
|
||||
RawBuffer<> data;
|
||||
|
||||
const dom::Element* domElem = nullptr;
|
||||
ErrorResult* out_domElemError = nullptr;
|
||||
};
|
||||
|
||||
namespace webgl {
|
||||
|
||||
struct TexUnpackBlobDesc final {
|
||||
GLenum imageTarget = LOCAL_GL_TEXTURE_2D;
|
||||
uvec3 size;
|
||||
gfxAlphaType srcAlphaType = gfxAlphaType::NonPremult;
|
||||
|
||||
Maybe<RawBuffer<>> cpuData;
|
||||
Maybe<uint64_t> pboOffset;
|
||||
RefPtr<layers::Image> image;
|
||||
RefPtr<gfx::DataSourceSurface> surf;
|
||||
|
||||
WebGLPixelStore unpacking;
|
||||
};
|
||||
|
||||
} // namespace webgl
|
||||
|
||||
// ---------------------------------------
|
||||
// MakeRange
|
||||
|
||||
inline Range<uint8_t> ByteRange(const mozilla::ipc::Shmem& shmem) {
|
||||
return {shmem.get<uint8_t>(), shmem.Size<uint8_t>()};
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline Range<const T> MakeRange(T (&arr)[N]) {
|
||||
return {arr, N};
|
||||
|
|
|
@ -5432,6 +5432,7 @@ fail-if = (os == 'linux')
|
|||
subsuite = webgl2-core
|
||||
[generated/test_2_conformance2__state__gl-object-get-calls.html]
|
||||
subsuite = webgl2-core
|
||||
skip-if = 1
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_2_conformance2__sync__sync-webgl-specific.html]
|
||||
subsuite = webgl2-core
|
||||
|
@ -12280,6 +12281,7 @@ subsuite = webgl1-core
|
|||
subsuite = webgl1-core
|
||||
[generated/test_conformance__state__gl-object-get-calls.html]
|
||||
subsuite = webgl1-core
|
||||
skip-if = 1
|
||||
[generated/test_conformance__state__state-uneffected-after-compositing.html]
|
||||
subsuite = webgl1-core
|
||||
[generated/test_conformance__textures__canvas__tex-2d-alpha-alpha-unsigned_byte.html]
|
||||
|
|
|
@ -73,6 +73,14 @@ skip-if = (os == 'android') || (os == 'linux') || (os == 'win')
|
|||
[generated/test_conformance__ogles__GL__mat3__mat3_001_to_006.html]
|
||||
# Timeout on D3D11
|
||||
skip-if = (os == 'win')
|
||||
[generated/test_conformance__state__gl-object-get-calls.html]
|
||||
# Really really slow on IPC mode. Update test suite to get faster/quick-mode test.
|
||||
skip-if = 1
|
||||
[generated/test_2_conformance2__state__gl-object-get-calls.html]
|
||||
# Really really slow on IPC mode. Update test suite to get faster/quick-mode test.
|
||||
skip-if = 1
|
||||
# Also fails on Linux still?
|
||||
fail-if = (os == 'linux')
|
||||
|
||||
########################################################################
|
||||
# Global
|
||||
|
@ -799,8 +807,6 @@ fail-if = (os == 'linux')
|
|||
fail-if = (os == 'linux')
|
||||
[generated/test_2_conformance2__state__gl-get-calls.html]
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_2_conformance2__state__gl-object-get-calls.html]
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_2_conformance__state__gl-get-calls.html]
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_2_conformance__glsl__bugs__sampler-array-using-loop-index.html]
|
||||
|
|
Загрузка…
Ссылка в новой задаче