User Images
On this page
User images is a feature of Gameface that allows developers to manually load and decode textures (which Cohtml would normally do). User images also allows you to specify a content rectangle where the actual image is. This can be used if the texture has padding or is part of a texture atlas.
This lets you achieve the following:
- Improve the loading time of pages by preparing the textures in advance instead of when Cohtml asks for them.
- Reduce memory footprint when the engine and the UI share textures, by having the texture stored in GPU memory only once, instead of twice (once for the engine and once for Cohtml).
- Use custom image formats.
Using user images for preloading textures
Cohtml expects all textures to have pre-multiplied alpha, keep that in mind when loading the images (unless the default shaders / backends are replaced).
- Override
cohtml::IAsyncResourceHandler::OnResourceRequest
in the resource handler.
The engine must keep the texture alive while it is being used by Cohtml.
virtual void MyResponseHandler::OnResourceRequest(const cohtml::IAsyncResourceRequest* request, cohtml::IAsyncResourceResponse* response) override
{
std::string url = request->GetURL();
if (MyApp::IsPreloaded(url))
{
auto texture = MyApp::GetPreloadedTexture(url);
// Provide texture information to Cohtml
cohtml::IAsyncResourceResponse::UserImageData data;
data.Width = texture->Width;
data.Height = texture->Height;
data.ContentRectWidth = texture->Width;
data.ContentRectHeight = texture->Height;
data.Format = texture->Format;
data.Texture = texture->Resource;
response->ReceiveUserImage(data);
response->Finish(cohtml::IAsyncResourceResponse::Status::Success);
}
else
{
HandleNonPreloadedResourceRequest(request, response);
}
}
- Modify the rendering backends to keep track of user textures. When
WrapUserTexture
is called, you should mark the texture as a user texture.
void MyBackend::WrapUserTexture(void* userObject,
const Texture2D& description,
Texture2DObject object)
{
// userObject contains whatever you have passed to
// cohtml::IAsyncResourceResponse::UserImageData::Texture
WrappedTexture t;
t.Texture = userObject;
t.IsUserTexture = true;
m_Textures.insert(object, t);
}
When DestroyTexture
is called, you should notify your engine that the texture is not used anymore and clear the reference.
DestroyTexture
will be called when the texture is not referenced by any HTML element or JS object.void MyBackend::DestroyTexture(Texture2DObject texture)
{
auto t = m_Textures.find(texture);
if (t != m_Textures.end())
{
if (t->second.IsUserTexture)
{
MyApp->TextureReleased(t->second.Texture);
}
else
{
DestroyTextureImpl(t->second.Texture);
}
m_Textures.erase(t);
}
}
- Attach to the system callback
OnUserImageDropped
and notify your engine about textures that were dropped even before being used. For such textures theDestroyTexture
method won’t be called.
cohtml::SystemSettings CreateSystemSettings()
{
cohtml::SystemSettings systemSettings;
systemSettings.OnUserImageDropped = [](void* userData, void* userImage)
{
// userImage contains whatever you have passed to
// cohtml::IAsyncResourceResponse::UserImageData::Texture
static_cast<MyApp*>(userData)->TextureReleased(userImage);
};
systemSettings.UserData = this;
return systemSettings;
}
Lifetime of user image resources
References to the user images will be released after they are not referenced anymore by any HTML element or JS object. Removing an element that is using an user image from the DOM tree does not mean that the reference to the resource will be released immediately.
Reference flow when using user image resources as background-image
:
- Create an element with a style which has user image resource for a
background-image
. - When the element’s style is evaluated, the style will add a reference to the resource.
- The reference will be removed when:
- The
background-image
in the element’s style is changed. - The style of the element is removed or the whole element is removed from the DOM tree.
- The
Elements that are detached from the tree do not have styles.
Lifetime flow in <img>
:
- Create
<img>
element with a user image resource specified by thesrc
attribute. - The element will add a reference to the resource.
- The reference will be removed when:
- The
src
attribute is changed. - The Garbage Collector destroys the element.
- The
Non-user images work the same way, but they are cached internally by our SDK. They are going to be freed when the cache reaches the configured thresholds.