Bug 212470

Summary: [WebXR] Refactor OpenXR platform code
Product: WebKit Reporter: Sergio Villar Senin <svillar>
Component: New BugsAssignee: Sergio Villar Senin <svillar>
Status: RESOLVED FIXED    
Severity: Normal CC: darin, pnormand, sam, simon.fraser, svillar, webkit-bug-importer, youennf, ysuzuki, zan
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 213045    
Bug Blocks: 208988    
Attachments:
Description Flags
Patch
none
Patch
none
Patch youennf: review+

Description Sergio Villar Senin 2020-05-28 08:42:54 PDT
[WebXR] Refactor OpenXR platform code
Comment 1 Sergio Villar Senin 2020-05-28 09:00:07 PDT
Created attachment 400466 [details]
Patch
Comment 2 Sergio Villar Senin 2020-05-28 09:05:13 PDT
Created attachment 400468 [details]
Patch
Comment 3 Zan Dobersek 2020-05-29 03:09:24 PDT
Comment on attachment 400468 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=400468&action=review

> Source/WebCore/Modules/webxr/WebXRSystem.cpp:60
> +    return this == &other ? true : false;

Should be able to avoid the ternary operator.

> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:83
> +        RETURN_IF_FAILED(result, "xrEnumerateApiLayerProperties()", m_instance);

How is m_instance supposed to be used here when it's not yet initialized? It's passed to xrResultToString(), but the docs for that entrypoint suggest it must be a valid handle.

> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:149
> +Instance::Impl::~Impl()
> +{
> +}

Can be `= default;`-ed, unless it should destroy the XrInstance object.

> Source/WebCore/testing/WebFakeXRDevice.h:73
> +    bool operator==(const Device& other) const final { return this == &other ? true : false; }

As before, the ?: operator can be omitted.
Comment 4 Sergio Villar Senin 2020-05-29 03:35:43 PDT
Comment on attachment 400468 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=400468&action=review

Thanks for the review!

>> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:83
>> +        RETURN_IF_FAILED(result, "xrEnumerateApiLayerProperties()", m_instance);
> 
> How is m_instance supposed to be used here when it's not yet initialized? It's passed to xrResultToString(), but the docs for that entrypoint suggest it must be a valid handle.

It's initialized to XR_NULL_HANDLE but that's indeed an invalid handle. The Monado runtime early returns with invalid handles but I agree we're not respecting the API contract. 

I'll add a check in resultToString() before landing.

>> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:149
>> +}
> 
> Can be `= default;`-ed, unless it should destroy the XrInstance object.

Right, we should call xrDestroyInstance here.
Comment 5 youenn fablet 2020-05-29 03:36:11 PDT
Comment on attachment 400468 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=400468&action=review

> Source/WebCore/platform/xr/PlatformXR.h:55
> +    virtual bool operator==(const Device& other) const = 0;

In theory, we could have A == B be true and B == A be false.
Maybe we should have a function operator==(const Device&, const Device&) that would return false if the two device types are not the same derived type.
Comment 6 Sergio Villar Senin 2020-05-29 04:56:45 PDT
(In reply to youenn fablet from comment #5)
> Comment on attachment 400468 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=400468&action=review
> 
> > Source/WebCore/platform/xr/PlatformXR.h:55
> > +    virtual bool operator==(const Device& other) const = 0;
> 
> In theory, we could have A == B be true and B == A be false.
> Maybe we should have a function operator==(const Device&, const Device&)
> that would return false if the two device types are not the same derived
> type.

I am not sure whether I understand this proposal. Looks like you are suggesting to replace the virtual member operator by a function operator to check that the derived types are the same.

My question is, where would you then define the operator== for the OpenXRDevice subclasses which compares the ids? Because all the code outside of platform (and WebCore/testing) should have to only deal with Device classes and not any of their subclasses.
Comment 7 Darin Adler 2020-05-29 10:21:21 PDT
Comment on attachment 400468 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=400468&action=review

>>> Source/WebCore/platform/xr/PlatformXR.h:55
>>> +    virtual bool operator==(const Device& other) const = 0;
>> 
>> In theory, we could have A == B be true and B == A be false.
>> Maybe we should have a function operator==(const Device&, const Device&) that would return false if the two device types are not the same derived type.
> 
> I am not sure whether I understand this proposal. Looks like you are suggesting to replace the virtual member operator by a function operator to check that the derived types are the same.
> 
> My question is, where would you then define the operator== for the OpenXRDevice subclasses which compares the ids? Because all the code outside of platform (and WebCore/testing) should have to only deal with Device classes and not any of their subclasses.

It’s true, virtual operators are typically not a good pattern. It’s easy to get them wrong.

I suggest we name this operation rather than overloading ==. Just call it isSameDevice.
If it’s an error to call this with a derived class pointer, then at the very least the derived classes should make their overloads private.
Comment 8 Sergio Villar Senin 2020-05-29 16:07:36 PDT
(In reply to Darin Adler from comment #7)
> Comment on attachment 400468 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=400468&action=review
> 
> >>> Source/WebCore/platform/xr/PlatformXR.h:55
> >>> +    virtual bool operator==(const Device& other) const = 0;
> >> 
> >> In theory, we could have A == B be true and B == A be false.
> >> Maybe we should have a function operator==(const Device&, const Device&) that would return false if the two device types are not the same derived type.
> > 
> > I am not sure whether I understand this proposal. Looks like you are suggesting to replace the virtual member operator by a function operator to check that the derived types are the same.
> > 
> > My question is, where would you then define the operator== for the OpenXRDevice subclasses which compares the ids? Because all the code outside of platform (and WebCore/testing) should have to only deal with Device classes and not any of their subclasses.
> 
> It’s true, virtual operators are typically not a good pattern. It’s easy to
> get them wrong.
> 
> I suggest we name this operation rather than overloading ==. Just call it
> isSameDevice.
> If it’s an error to call this with a derived class pointer, then at the very
> least the derived classes should make their overloads private.

Well I was overloading == because I want all the operations in containers to just work without any extra code. What would you suggest?

In the end we might now strictly need it because those containers will typically store a Ref<>, RefPtr<> of those objects.

Another option could be to just keep the current code, i.e., we generate consecutive integers to identify devices and that's it.
Comment 9 Sergio Villar Senin 2020-05-29 16:08:36 PDT
(In reply to Sergio Villar Senin from comment #8) 
> In the end we might now strictly need it because those containers
                      ^^^
                      not
Comment 10 Darin Adler 2020-05-29 16:23:52 PDT
Comment on attachment 400468 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=400468&action=review

>>>>> Source/WebCore/platform/xr/PlatformXR.h:55
>>>>> +    virtual bool operator==(const Device& other) const = 0;
>>>> 
>>>> In theory, we could have A == B be true and B == A be false.
>>>> Maybe we should have a function operator==(const Device&, const Device&) that would return false if the two device types are not the same derived type.
>>> 
>>> I am not sure whether I understand this proposal. Looks like you are suggesting to replace the virtual member operator by a function operator to check that the derived types are the same.
>>> 
>>> My question is, where would you then define the operator== for the OpenXRDevice subclasses which compares the ids? Because all the code outside of platform (and WebCore/testing) should have to only deal with Device classes and not any of their subclasses.
>> 
>> It’s true, virtual operators are typically not a good pattern. It’s easy to get them wrong.
>> 
>> I suggest we name this operation rather than overloading ==. Just call it isSameDevice.
>> If it’s an error to call this with a derived class pointer, then at the very least the derived classes should make their overloads private.
> 
> Well I was overloading == because I want all the operations in containers to just work without any extra code. What would you suggest?
> 
> In the end we might now strictly need it because those containers will typically store a Ref<>, RefPtr<> of those objects.
> 
> Another option could be to just keep the current code, i.e., we generate consecutive integers to identify devices and that's it.

OK. Please give me one or more specific examples of a useful container operation so I can consider the value and comment.
Comment 11 Darin Adler 2020-05-29 16:24:21 PDT
Comment on attachment 400468 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=400468&action=review

>>>>>> Source/WebCore/platform/xr/PlatformXR.h:55
>>>>>> +    virtual bool operator==(const Device& other) const = 0;
>>>>> 
>>>>> In theory, we could have A == B be true and B == A be false.
>>>>> Maybe we should have a function operator==(const Device&, const Device&) that would return false if the two device types are not the same derived type.
>>>> 
>>>> I am not sure whether I understand this proposal. Looks like you are suggesting to replace the virtual member operator by a function operator to check that the derived types are the same.
>>>> 
>>>> My question is, where would you then define the operator== for the OpenXRDevice subclasses which compares the ids? Because all the code outside of platform (and WebCore/testing) should have to only deal with Device classes and not any of their subclasses.
>>> 
>>> It’s true, virtual operators are typically not a good pattern. It’s easy to get them wrong.
>>> 
>>> I suggest we name this operation rather than overloading ==. Just call it isSameDevice.
>>> If it’s an error to call this with a derived class pointer, then at the very least the derived classes should make their overloads private.
>> 
>> Well I was overloading == because I want all the operations in containers to just work without any extra code. What would you suggest?
>> 
>> In the end we might now strictly need it because those containers will typically store a Ref<>, RefPtr<> of those objects.
>> 
>> Another option could be to just keep the current code, i.e., we generate consecutive integers to identify devices and that's it.
> 
> OK. Please give me one or more specific examples of a useful container operation so I can consider the value and comment.

Typically you can’t store a polymorphic object in a container: As you said you’ll be storing pointers in the containers.
Comment 12 Sergio Villar Senin 2020-06-05 03:20:50 PDT
Created attachment 401135 [details]
Patch
Comment 13 Sergio Villar Senin 2020-06-05 03:27:40 PDT
Darin, Youenn PTAL

I finally removed the equality operator overloading. So far there is no need for them.
Comment 14 youenn fablet 2020-06-05 04:16:33 PDT
Comment on attachment 401135 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=401135&action=review

> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:95
> +    }();

Why do we need these lambdas? It seems its purpose is to not do an if/else.
Can we remove them, maybe by using functions with a name that will tell what it does?

> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:157
> +    XrResult result = xrEnumerateViewConfigurations(m_instance, device.xrSystemId(), 0, &viewConfigurationCount, nullptr);

auto

> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:167
> +        WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());

No need for these two WTFLogAlways.
Maybe we should use RELEASE_LOG(XR, ...) as well instead.

> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:182
> +            supportedModes.append(SessionMode::ImmersiveVr);

Should we use a switch here?
Comment 15 Sergio Villar Senin 2020-06-05 09:15:43 PDT
Comment on attachment 401135 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=401135&action=review

Thanks for the review!

>> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:95
>> +    }();
> 
> Why do we need these lambdas? It seems its purpose is to not do an if/else.
> Can we remove them, maybe by using functions with a name that will tell what it does?

Also creating different scopes for variables with the same name. But yeah we don't really need them.

>> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:157
>> +    XrResult result = xrEnumerateViewConfigurations(m_instance, device.xrSystemId(), 0, &viewConfigurationCount, nullptr);
> 
> auto

OK.

>> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:167
>> +        WTFLogAlways("xrEnumerateViewConfigurations(): error %s\n", resultToString(result, m_instance).utf8().data());
> 
> No need for these two WTFLogAlways.
> Maybe we should use RELEASE_LOG(XR, ...) as well instead.

The duplication is likely a merge issue. I'll replace them by the RELEASE_LOG.

>> Source/WebCore/platform/xr/openxr/PlatformXROpenXR.cpp:182
>> +            supportedModes.append(SessionMode::ImmersiveVr);
> 
> Should we use a switch here?

OK
Comment 16 Sergio Villar Senin 2020-06-10 06:17:39 PDT
Committed r262838: <https://trac.webkit.org/changeset/262838>
Comment 17 Radar WebKit Bug Importer 2020-06-10 06:18:19 PDT
<rdar://problem/64206806>
Comment 18 Yusuke Suzuki 2020-06-10 13:13:02 PDT
Re-opened since this is blocked by bug 213045
Comment 19 Philippe Normand 2020-06-10 13:46:45 PDT
Sorry I managed to fix that one. Closing.